Einleitung Modellannahmen Internes vs Externes Sortieren Qualit¨atsbeurteilungen Leistungsnachweis

Sortierverfahren Einleitung

Lutz Wegner

17. April 2014

1 / 34 Einleitung Modellannahmen Internes vs Externes Sortieren Qualit¨atsbeurteilungen Leistungsnachweis Inhaltsverzeichnis 1 Einleitung Warum Sortierverfahren? Sortieren und Suchen als algorithmische Herausforderung 2 Modellannahmen Ein realistisches Modell Offen gelassene Punkte 3 Internes vs Externes Sortieren Internes Sortieren (Hauptspeichersort) Externes Sortieren (Plattensortierung) 4 Qualit¨atsbeurteilungen Asymptotische und gemessene Laufzeiten Zus¨atzlicher Platz Stabilit¨at und Smoothness Praktische Ub¨ erlegungen Taxonomie 5 Leistungsnachweis

Ihre Aufgabe 2 / 34 Einleitung Modellannahmen Internes vs Externes Sortieren Qualit¨atsbeurteilungen Leistungsnachweis Warum Sortierverfahren?

Einer Studie aus den Achtzigern zufolge verbringen Mainframes 25 % ihrer CPU-Zeit mit Sortiervorg¨angen. Betrachte hierzu Join und Projektion in Datenbanken.

select STUDENTS.NAME, COURSE, DEPT from SIGN_UP, STUDENTS where SIGN_UP.NAME = STUDENTS.NAME

3 / 34 Einleitung Modellannahmen Internes vs Externes Sortieren Qualit¨atsbeurteilungen Leistungsnachweis

Tabelle 1: SIGN UP Tabelle 2: STUDENTS NAME COURSE NAME SEM DEPT Jones ALG+DS Smith 1 CSC Smith DB1 Miller 5 MATH Miller ALG+DS Jones 1 MATH Smith PROG1 Clark 3 CSC Clark DB1 Jones PROG1 Tabelle 3: SIGN UP ./ STUDENTS NAME COURSE DEPT Jones ALG+DS MATH Smith DB1 CSC Miller ALG+DS MATH Smith PROG1 CSC Clark DB1 CSC Jones PROG1 MATH

4 / 34 Einleitung Modellannahmen Internes vs Externes Sortieren Qualit¨atsbeurteilungen Leistungsnachweis

Das Datenbankbeispiel deutet auch an, wie wichtig die Erkennung und Eliminierung von Duplikaten ist, z. B. nach einer Projektion auf NAME im Ergebnis oben, wenn im SQL-Befehl die DISTINCT-Klausel enthalten war.

Indeed, I believe that virtually every important aspect of programming arises somewhere in the context of sorting and searching! [Knu98, p. v]

5 / 34 Einleitung Modellannahmen Internes vs Externes Sortieren Qualit¨atsbeurteilungen Leistungsnachweis

Sortieren ist ein ideales Anwendungsgebiet fur¨ Algorithmenentwurf und Software Engineering Studien zu Effizienz und Laufzeitverhalten (performance evaluation) konkrete Komplexit¨atstheorie und hatte seinen ersten H¨ohepunkt in den funfziger¨ und sechziger Jahren, wie man an den Referenzen hier sieht ACM Symp. on Sorting, Nov. 1962 and CACM May 1963 Knuth’s bibliography in Computing Reviews 13 (1972) wurde aber immer wieder neu belebt, z. B. in dem Uberblicksartikel¨ IEEE TC Special issue on sorting, April 1985

6 / 34 Einleitung Modellannahmen Internes vs Externes Sortieren Qualit¨atsbeurteilungen Leistungsnachweis Realistische Modellannahmen

Knuth [Knu98, p. 4] schl¨agt das folgende Modell vor. Gegeben sind N S¨atze (Objekte, items, records)

R1, R2, ..., RN

die zusammen eine Datei (a file) bilden. Jeder Satz Rj hat einen Schlussel¨ (key), Kj , der die Sortierung bestimmt. Zus¨atzlich kann der Satz weitere Informationen (sog “satellite information”) enthalten. Man definiert dann eine Ordnungsrelation (ordering relation)“<” uber¨ dem Schlusselraum¨ mit der Eigenschaft, dass fur¨ beliebige drei Schlusselwerte¨ a, b, c, gilt: genau eine der M¨oglichkeiten a < b, a = b, b < a ist wahr (law of trichotomy) wenn a < b und b < c, dann auch a < c (law of transitivity) Somit wird eine lineare (totale) Ordnung vorausgesetzt. 7 / 34 Einleitung Modellannahmen Internes vs Externes Sortieren Qualit¨atsbeurteilungen Leistungsnachweis Offen gelassene Punkte

Das Ziel einer Sortierung ist es, eine Permutation p(1)p(2) ... p(N) der S¨atze zu finden, bei der die Schlussel¨ in nicht-absteigender Reihenfolge stehen:

Kp(1) ≤ Kp(2) ≤ · · · ≤ Kp(N). Die folgenden Punkte bleiben offen: Wie werden die Datens¨atze geliefert (Band, Platte, on-line)? Wie viele S¨atze sind gegeben und ist die Anzahl vorher bekannt? Ist der Wertebereich der Schlussel¨ bekannt (begrenzt)? Welche Operationen sind erlaubt (nur Schlusselvergleiche,¨ arithmetische Operationen)? Wie erfolgt die Umordnung der S¨atze? Gibt es eine bekannte Anfangsordnung? Wie viel Extraplatz ist verfugbar?¨ 8 / 34 Einleitung Modellannahmen Internes vs Externes Sortieren Qualit¨atsbeurteilungen Leistungsnachweis Internes versus Externes Sortieren

Traditionell unterscheidet man zwei Untermodelle Sortieren eines Array (eines per Index adressierbaren Felds) im Hauptspeicher Sortieren einer Plattendatei

9 / 34 Einleitung Modellannahmen Internes vs Externes Sortieren Qualit¨atsbeurteilungen Leistungsnachweis Internes Sortieren (Hauptspeichersortierung)

Dieses Modell setzt eine Datenstruktur ¨ahnlich zu der unten in PASCAL-Notation gegebenen voraus. TYPE item = RECORD key : integer; info : infotype END; sequence = ARRAY[1..N] OF item; VAR a : sequence; Wir wollen jetzt eine Prozedur XYZ-Sort(VAR s : sequence); erstellen, die – bei Aufruf mit XYZ-Sort(a) – den Array a so umordnet, dass danach gilt

a[i].key ≤ a[i+1].key ∀ i (1 ≤ i < N). 10 / 34 Einleitung Modellannahmen Internes vs Externes Sortieren Qualit¨atsbeurteilungen Leistungsnachweis Modellannahmen fur¨ Hauptspeichersortierung

Die Annahmen in diesem Modell sind: Die S¨atze k¨onnen getauscht werden, was u. U. gleiche, feste L¨angen voraussetzt. Der Zugriff auf jeden Satz erfolgt mit gleichen Kosten (uniform cost model). Die Ordnung bestimmt sich nur uber¨ Schlusselvergleiche.¨ Alle S¨atze passen in den Hauptspeicher. Im einfachen Fall bleiben auch alle Parallelit¨atsaspekte außen vor.

11 / 34 Einleitung Modellannahmen Internes vs Externes Sortieren Qualit¨atsbeurteilungen Leistungsnachweis Externes Sortieren (Plattensortierung)

Der Begriff “Plattendatei” (disc file) bezieht sich auf alle Dateien auf externen Medien mit wahlfreiem Zugriff auf einzelne S¨atze (random access), im Gegensatz zu B¨andern oder Streams. Die entsprechende Datenstruktur sieht jetzt wie folgt aus (wieder in PASCAL-Notation).

TYPE page = ARRAY[1..s] OF item; file = ARRAY[1..M] OF page; buffer = ARRAY[1..k] OF page; VAR f : file;

12 / 34 Einleitung Modellannahmen Internes vs Externes Sortieren Qualit¨atsbeurteilungen Leistungsnachweis Modellannahmen fur¨ Plattensortierung

Die Annahmen fur¨ eine sinnvolle Diskussion spiegeln die klassische Speicherhierarchie wider: k  M und k ist fest w¨ahrend der Ausfuhrung¨ die Seitengr¨oße ist fest vorgegeben, z. B. 4 KB die Datei passt nicht in den Hauptspeicher der Zugriff ist nicht gleich teuer fur¨ alle Seiten auf der Platte Ein-/Ausgabezeiten bestimmen die Gesamtausfuhrungszeit¨ (mit Ausnahmen) innerhalb einer Seite sind die S¨atze linear geordnet Seiten, die die Datei belegt, sind nicht notwendigerweise aufeinanderfolgend und linear geordnet innerhalb der Zylinder Zylinder, die die Datei belegt, sind nicht notwendigerweise aufeinanderfolgend und linear geordnet die Seitenersetzung kann vom Anwender kontrolliert werden

13 / 34 Einleitung Modellannahmen Internes vs Externes Sortieren Qualit¨atsbeurteilungen Leistungsnachweis Andere Modelle

Andere untersuchenswerte Modelle sind: Sortieren linearer Listen (chained nodes, internes Sortieren) Sortieren mit Parallelverarbeitung (VLSI, SIMD) Sortieren in Netzwerken (LAN, WAN) Sortieren von B¨andern (auch bubble memory) Hauptspeichersortierverfahren im virtuellen Adressraum (paged memory sorting)

14 / 34 Einleitung Modellannahmen Internes vs Externes Sortieren Qualit¨atsbeurteilungen Leistungsnachweis Asymptotische und gemessene Laufzeiten

Neben der Messung der tats¨achlichen Laufzeiten eines Programms fur¨ verschiedene Eingaben, die von der Programmiersprache und dem Rechner abh¨angen, ist es ublich¨ die Leistungsf¨ahigkeit in einer abstrakteren Art zu messen (zu analysieren). Z¨ahlen kann man Schlusselvergleiche¨ Plattenzugriffe MIX-Instruktionen elementare PASCAL-, C-, Java-, . . . Instruktionen Schleifendurchg¨ange (Iterationen) Satzvertauschungen (record exchanges, moves) im besten, mittleren, schlechtesten Fall, fur¨ bestimmte Schlusselbereiche,¨ unterschiedliche Dateigr¨oßen, Vorsortierungen und Multimengen. Das Ergebnis schreibt man immer als Funktion der L¨ange n der Eingabe auf, meist in der “Big-Oh-Notation”.

15 / 34 Einleitung Modellannahmen Internes vs Externes Sortieren Qualit¨atsbeurteilungen Leistungsnachweis Big-Oh- und Big-Omega-Notation

Es gelte f (n) = O(g(n))

gdw. es Konstanten k und n0 gibt, so dass

|f (n)| ≤ k · |g(n)| ∀n > n0.

Damit gibt man eine obere Schranke fur¨ die Wachstumsrate der Funktion an, die multiplikative und additive Konstanten ignoriert. Das rechtfertigt dann den Begriff der asymptotischen Laufzeit. Eine untere Schranke gibt man in der “Big-Omega-Notation” an:

f (n) = Ω(g(n)) gdw. g(n) = O(f (n))

Genauer, es gibt eine Konstante k, so dass

f (n) ≥ k · g(n) unendlich oft.

16 / 34 Einleitung Modellannahmen Internes vs Externes Sortieren Qualit¨atsbeurteilungen Leistungsnachweis Little-oh- und Big-Theta-Notation

Weniger h¨aufig ist die “Little-oh-Notation”

f (n) f (n) = o(g(n)) gdw. lim = 0 n→∞ g(n)

die angibt, dass f (n) asymptotisch langsamer w¨achst als g(n). Insbesondere setzen wir voraus, dass – bei Angabe einer Funktion f (n) = O(g(n)) – man keine Funktion h(n) = o(g(n)) kennt, so dass f (n) = O(h(n)), d. h. wenn wir eine obere Schranke benennen, dann sollte sie die knappm¨oglichste sein. Obere und untere Schranke zusammen bilden die “Big-Theta-Notation”

f (n) = Θ(g(n)) gdw. f (n) = O(g(n)) und f (n) = Ω(g(n)).

17 / 34 Einleitung Modellannahmen Internes vs Externes Sortieren Qualit¨atsbeurteilungen Leistungsnachweis Gemessene Laufzeiten I

Auch wenn es gelingt, die asymptotische Laufzeit zu analysieren (was schwierig sein kann), ist es oft nutzlich,¨ die konstanten Faktoren der Laufzeit zu ermitteln und zu vergleichen. Wie groß ist die Aufsetzzeit des Programms (Initialisierungen)? Kann man innere Schleifen optimieren? Bringen so genannte “Verbesserungen” wirklich was, z. B. Entfernung von rekursiven Aufrufen am Ende einer Prozedur (removal of tail recursion)? Gibt es eine sowohl kurze als auch effiziente Implementierung eines speziellen Algorithmus?

18 / 34 Einleitung Modellannahmen Internes vs Externes Sortieren Qualit¨atsbeurteilungen Leistungsnachweis Gemessene Laufzeiten II

Das Problem ist, wie schon erw¨ahnt, dass alle Messungen relativ zu einem Rechner, einer Programmiersprache, einer Implementierung der Vergleichsumgebung sind. L¨auft der Vergleich in einer Multi-tasking-Umgebung, kann “cycle stealing” auftreten und die Laufzeiten h¨angen dann von der Systembelastung ab.

Trotzdem sind paarweise Vergleiche unter gleichen Testbedingungen sinnvoll und eine klare Uberlegenheit¨ eines Verfahrens uber¨ andere (das Ranking) stellt eine wichtige Information dar. Diese Aussagen bleiben auch dann noch gultig,¨ wenn durch den technischen Wandel die absoluten Laufzeiten schon lange veraltet sind.

19 / 34 Einleitung Modellannahmen Internes vs Externes Sortieren Qualit¨atsbeurteilungen Leistungsnachweis Arrays, Listen, Hashmaps  Moderne Programmiersprachen haben oft eigene Vorstellungen, was eine Liste oder ein Array ist. Traditionell ist eine Liste als Datenstruktur eine einfach oder doppelt verkettete Folge von Knoten ohne wahlfreien Zugriff, aber mit einem Pointer auf den Nachfolger. Dafur¨ k¨onnen einzelne Knoten im Heapbereich des Programms angelegt und gel¨oscht werden.

Betrachtet man z. B. die Scriptsprache Tcl, so ist eine Liste eigentlich ein Array, denn es gibt Listenkommandos fur¨ den Zugriff auf das i-te Element. Dagegen ist das, was in Tcl wie ein Array aussieht, in Wirklichkeit ein assoziativer Speicherbereich (hashmap), d.h. der Zugriff auf einzelne Elemente erfolgt durch eine Schlusseltransformation,¨ die Kollissionen m¨oglichst vermeidet. Bei Arrays und Hashspeichern verlangen nachtr¨agliche Gr¨oßen¨anderungen ein teures Umkopieren der Datenstruktur.

20 / 34 Einleitung Modellannahmen Internes vs Externes Sortieren Qualit¨atsbeurteilungen Leistungsnachweis Zus¨atzlicher Platz

Per Konvention z¨ahlt das Wandeln einer Array-Eingabe in eine Listen-Eingabe (Hinzufugen¨ von n Zeigern) als O(n) extra Platz. Das gilt nicht, wenn die Eingabe sowieso eine verkettete Liste ist. Die Maßeinheit fur¨ Platz ist Worte, was aber im Grunde dasselbe wie Bytes ist in der Big-Oh-Notation, oder in Bits, falls man genauer sein will. Insbesondere spricht man von in situ Sortieren, wenn h¨ochstens O((log n)2) extra Bits erlaubt sind, was einem Stapel mit logarithmischer (in der Gr¨oße n der Eingabe) H¨ohe entspricht, bei dem jedes Stapelelement eine bin¨are Repr¨asentation ganzer Zahlen in der Gr¨oßenordnung n aufnehmen kann. Dagegen spricht man von minimal storage sorting, also Sortieren mit minimalem Platz, wenn nur O(1) extra Platz erlaubt ist. Allerdings ...

21 / 34 Einleitung Modellannahmen Internes vs Externes Sortieren Qualit¨atsbeurteilungen Leistungsnachweis Begriffsverwirrung I

 Unglucklicherw¨ eise sieht es so aus, als ob die Begriffe in-place, am Ort (lateinisch in situ) inkonsistent in der Literatur verwendet werden. Erkennbar ist eine Tendenz, damit nur konstant viel extra Platz zu erlauben, also nur O(1) zus¨atzliche Computerworte [Wik13]. Andererseits bezeichnen fast alle Lehrbucher¨ als in situ Sortierverfahren, obwohl der Algorithmus beim Sortieren von n S¨atzen einen Stapel mit O(log n) Worten fur¨ die Rekursion ben¨otigt, was der O(1)-Definition von in situ widerspricht.

22 / 34 Einleitung Modellannahmen Internes vs Externes Sortieren Qualit¨atsbeurteilungen Leistungsnachweis Begriffsverwirrung II

Umgekehrt stammt der Begriff minimum storage von Knuth (Exercise 3 in Section 5.5 [Knu98, p. 390]) und wird dort als O((log n)2) extra Bits definiert. Das ist verwirrend, weil im Sprachgebrauch “Minimum” den kleinsten Wert bezeichnen sollte, offensichtlich aber O(1) (in situ) asymptotisch kleiner ist als O((log n)2) (minimum storage). Daher reden wir bei O(1) lieber von minimalem Extraplatz. Wie auch immer, jetzt wo die Konfusion in die Welt gesetzt wurde, l¨asst sich die Ordnung auch mit noch so vielen Worten nicht mehr herstellen.

23 / 34 Einleitung Modellannahmen Internes vs Externes Sortieren Qualit¨atsbeurteilungen Leistungsnachweis Plattendateien am Ort sortieren?

Bei der Diskussion externer Sortierverfahren meint man mit extra Platz sowohl Platz auf der Platte als auch im Hauptspeicher. Heute ist Internspeicher allerdings nicht mehr so knapp wie fruher.¨ Fasst man ein externes Sortierverfahren ins Auge, das auch auf der Platte in situ ist, sollte man die M¨oglichkeit eines Systemcrashs bedenken, was zu dauerhaftem Datenverlust fuhren¨ k¨onnte.

24 / 34 Einleitung Modellannahmen Internes vs Externes Sortieren Qualit¨atsbeurteilungen Leistungsnachweis Stabilit¨at und Smoothness I

Ein Sortieralgorithmus heißt stabil (engl. stable1), wenn gleiche Schlussel¨ ihre relative Eingabeordnung bewahren [Knu98, p. 4]. Als Beispiel betrachte man eine Datei mit Passagiernamen und Flugnummer, die nach Passagiernamen sortiert ist. Wird diese Datei nach Flugnummer umsortiert, stehen bei einem stabilen Sortierverfahren alle Passagiere eines Flugs weiterhin in nach Namen aufsteigender Folge im Ergebnis.

1Im Englischen heißt das Gegenteil oft nonstable statt sprachlich richtig unstable, weil man die Verwechslung mit unreliable meiden m¨ochte. 25 / 34 Einleitung Modellannahmen Internes vs Externes Sortieren Qualit¨atsbeurteilungen Leistungsnachweis Stabilit¨at und Smoothness II

Ein weiteres Beispiel w¨are ein blindes Bieterverfahren in einer Auktion, wo die abgegebenen Angebote in zeitlicher Reihenfolge (seriell) gespeichert werden. Wird die Datei nach Angebotsh¨ohe sortiert, behalten Angebote mit gleichem Preis die Reihenfolge des Eingangs, was wichtig sein kann fur¨ die Bestimmung des Gewinners, vorausgesetzt man speichert nicht den Zeitpunkt des Eingangs. Das Problem ist in gewisser Weise auch verwandt mit der Beschleunigung bei Vorliegen von Multimengen (engl. multisets, bags). Dazu gleich mehr ...

26 / 34 Einleitung Modellannahmen Internes vs Externes Sortieren Qualit¨atsbeurteilungen Leistungsnachweis Smoothness

Der Begriff smoothness beim Sortieren wurde von Edsger W. Dijkstra 1981 eingefuhrt,¨ als er eine -Variante vorstellte, die er dann 1982 als ver¨offentlichte [Dij82]. Ein Sortierverfahren ist smooth, wenn sich seine Laufzeit von O(N log N) zu O(N) fur¨ vorsortierte oder un¨are Eingaben der Gr¨oße N verbessert. Insbesondere erfullt¨ ein Sortierverfahren fur¨ Multimengen mit einer Laufzeit

T (N) = O(N log n),

wobei n die Anzahl der unterschiedlichen Schlussel¨ ist, diese Definition.

27 / 34 Einleitung Modellannahmen Internes vs Externes Sortieren Qualit¨atsbeurteilungen Leistungsnachweis Praktische Ub¨ erlegungen

Ein Sortierverfahren sollte so einfach und “gutmutig”¨ wie m¨oglich sein. Vorzugsweise sollte fur¨ das Verfahren gelten, dass es keine Stopper +∞, −∞ braucht numerische und Textschlussel¨ verkraftet mit variabel langen S¨atzen umgehen kann wenig in der Laufzeit variiert leicht zu programmieren und zu warten, kurz und verifiziert ist nicht spezielle Architekturen verlangt wiederanlauff¨ahig ist gut in einer Paging-Umgebung l¨auft netzwerkf¨ahig mit verteilten Dateien ist auf einer SIMD-, MIMD-Maschine ausfuhrbar¨ ist verschr¨ankten E/A-Verkehr erlaubt (interleaving) auf- und absteigende Sortierung erlaubt Duplikate on-the-fly erkennt und eliminiert mit zusammengesetzten Schlusseln¨ klarkommt 28 / 34 Einleitung Modellannahmen Internes vs Externes Sortieren Qualit¨atsbeurteilungen Leistungsnachweis Varianten fur¨ den industriellen Einsatz

 Ein gutes Beispiel ist die Quicksort-Variante fur¨ die UNIX Software-Bibliothek, die von J. L. Bentley und M. D. McIlroy in [BM93] vorgestellt wird. Wir kommen darauf in der letzten Vorlesung zuruck.¨

29 / 34 Einleitung Modellannahmen Internes vs Externes Sortieren Qualit¨atsbeurteilungen Leistungsnachweis Die MIX-Tabelle aus Knuth Vol. 3

Knuths Band 3 (Sorting and Searching) enth¨alt eine Tabelle [Knu98, p. 382] “A Comparison of Internal Sorting Methods Using the MIX Computer”. Diese liefert die asymptotischen Laufzeiten (Durchschnitt und Maximum), Anzahl der ausgefuhrten¨ MIX Instruktionen fur¨ Eingabel¨angen N = 16 und N = 1000, Platzbedarf, L¨ange des Programmcodes und ob die Methode stabil ist. Die Angaben gelten fur¨ 14 Algorithmen aus dem Buch. Die Tabelle ist ein Wunder an Genauigkeit und druckt¨ aus, wie Donald Knuth Informatik mit Mathematik in seiner wissenschaftlichen Arbeit verbindet. Man sollte sie zu Rate ziehen, ehe man uber¨ die relativen Vorzuge¨ eines Sortierverfahrens gegenuber¨ anderen Verfahren diskutiert.

30 / 34 Einleitung Modellannahmen Internes vs Externes Sortieren Qualit¨atsbeurteilungen Leistungsnachweis

Abbildung 1: Die MIX-Tabelle aus Knuth Vol. 3 [Knu98, p. 382]

31 / 34 Einleitung Modellannahmen Internes vs Externes Sortieren Qualit¨atsbeurteilungen Leistungsnachweis

Sorting

by key comparisons other methods hashing ...

internal internal/external external

paging tags random “tapes” access parallel sequential machines machines

fixed flexible network network linked list sequential allocation

minimal storage in situ extra space

stable nonstable stable nonstable stable nonstable

Abbildung 2: Taxonomie fur¨ Sortierverfahren 32 / 34 Einleitung Modellannahmen Internes vs Externes Sortieren Qualit¨atsbeurteilungen Leistungsnachweis Was Sie beitragen mussen¨

Erstellen Sie eine Art Sorters Workbench (SWB) in einem in Java geschriebenen Projekt, mit dem Sie Sortieralgorithmen testen und bewerten k¨onnen Dazu geh¨ort eine Methode zur Datengenerierung, inkl. Vorsortierung und Multisets als Eingaben Eine Methode zur Ausgabekontrolle, inklusive Prufung¨ der Stabilit¨at Eine Methode, die das Ergebnis der Bewertung (Laufzeiten, Schlusselvergleiche)¨ speichert fur¨ sp¨atere Auswertungen Die Portierung von 3 – 4 Sortieralgorithmen von Pseudo-Pascal nach Java Eine genaue Aufgabenstellung folgt. Je zwei Studierende k¨onnen ein Team bilden. Ein Abschlussgespr¨ach kl¨art den eigenen Anteil an den L¨osungen. 33 / 34 Einleitung Modellannahmen Internes vs Externes Sortieren Qualit¨atsbeurteilungen Leistungsnachweis Literatur I

[BM93] Jon Luther Bentley and Malcolm Douglas McIlroy, Engineering a sort function, Software: Practice and Experience 23 (11) (1993), 1249–1265. [Dij82] Edsger W. Dijkstra, Smoothsort, an alternative for sorting in situ, Sci. Comput. Program. 1 (1982), no. 3, 223–233. [Knu98] Donald E. Knuth, The Art of Computer Programming. Vol. 3: Sorting and Searching, 2nd ed., vol. 3, Addison-Wesley, 1998. [Wik13] Wikipedia, In-place algorithm — wikipedia, the free encyclopedia, 2013, [Online; accessed 24-January-2013].

34 / 34 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur

Sortierverfahren Hoares Erfindung

Lutz Wegner

24. April 2014

1 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur Inhaltsverzeichnis

1 Der klassische Quicksort Hoares Originalver¨offentlichung Eine erste Implementierung

2 Lomutos Einwege-Quicksort Lomutos Pivotwahl Die Erfindung des Rads

3 Literatur

2 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur Hoares Originalver¨offentlichung

Im Jahr 1962 erfand Sir Charles Antony Richard Hoare, besser bekannt als Tony Hoare, einen rekursiven, in situ, Teile-und-Tausche (partition-exchange) Sortieralgorithmus, den er aufgrund seiner erkennbaren Effizienz Quicksort nannte [Hoa62].

3 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur

Listing 1: Quicksort allgemeines Schema. function Q u i c k s o r t (F : f i l e ): f i l e ; var H : keytype ; { p i v o t } F1 , F2 : f i l e ; begin i f | F | ≤ 1 then Quicksort := F { nothing to do} e l s e begin { Phase 1 − p a r t i t i o n } H := r1.key ; F1 := set of all ri ∈ F with ri .key ≤ H (i > 1) ; F2 := set of all ri ∈ F with ri .key ≥ H (i > 1) ; { Phase 2 − sort recursively } Quicksort := Quicksort(F1 ), r1 , Quicksort(F2 ) end { e l s e } end { Q u i c k s o r t }

4 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur Hardsplit/Easyjoin

Susan M. Merrit, die 1985 eine Taxonomie fur¨ Sortierverfahren aufstellte, nennt Quicksort ein hardsplit/easyjoin Sortierverfahren [Mer85]. Das bezieht sich auf die Tatsache, dass in der Teilephase die Schlusselvergleiche¨ und Austauschschritte erfolgen, w¨ahrend in der Rekursion nur buchgefuhrt¨ wird, was schon sortiert ist und was noch anliegt, aber keine Schlusselvergleiche¨ oder Datentransfers mehr stattfinden.

Eigentlich ist die Teilephase aber auch nicht so hart, da es eine sehr effiziente Implementierung – mit wechselseitigem Durchk¨ammen von links und rechts – fur¨ den paarweisen Austausch von S¨atzen gibt, deren Schlussel¨ “aus der Ordnung fallen”.

5 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur

H ≤ H ≥ ? ≤ ≥ H

i j

Abbildung 1: Zweiwege-Durchlauf mit Teilen&Tauschen.

Listing 2: Die inneren Schleifen fur¨ die Aufteilung. while i ≤ j do begin repeat i := i + 1 u n t i l a[i].key ≥ H ; repeat j := j − 1 u n t i l a[j].key ≤ H ; s w i t c h (a[i], a[j]) end { w h i l e } 6 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur Pivot-Element und swap()

Der Wert H, nach dem die Datei in jedem Rekursionsschritt geteilt wird, heißt Pivot, das franz¨osische Wort fur¨ Drehpunkt. Die Funktion switch(x, y) in der geschachtelten Schleife vertauscht die beiden Werte der Variablen x und y; oft heißt die Funktion auch swap(x, y) oder wird durch x :=: y angedeutet.

7 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur Schnell von Geburt an

Knuth [Knu98, p. 114] erw¨ahnt, dass alle Vergleiche gegen denselben Schlussel¨ H gemacht werden, den man in einem Register halten kann. Genauso k¨onnen die Variablen i und j in Registern verbleiben, die in den meisten Prozessorarchitekturen mit schnellen Pr¨ainkrement- und Pr¨adekrement-Befehlen fur¨ den Arrayzugriff hoch- und heruntergez¨ahlt werden.

Unten wird gezeigt, dass nur ungef¨ahr N/6 Austauschschritte fur¨ Folgen von N S¨atzen in einer zuf¨alligen Anordnung ben¨otigt werden. In anderen Worten, 2/3 aller S¨atze ver¨andern in jeder Teilungsphase ihren Platz nicht. Auch weiter unten erkl¨aren wir, warum es besser ist, auch bei Schlusseln¨ anzuhalten, die gleich dem Pivot H sind.

8 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur Von je drei publizierten Algorithmen ist einer fehlerhaft

Bei unserem eigenen Vorschlag fur¨ die Aufteilung im Programm auf Folie 6 erwartet man einen zus¨atzlichen Test vor dem Austausch der beiden gefundenen S¨atze. Musste¨ es da nicht heißen “if i < j then switch() else skip”, um den fehlerhaften Tausch am Ende zu verhindern, wenn i und j sich gekreuzt haben?

Ja und nein – ja, das w¨are eine einfache L¨osung; nein, wenn wir den Tausch beim Verlassen der Schleife ruckg¨ ¨angig machen. Bei dieser Strategie spekuliert man darauf, dass zwei zus¨atzliche switch()-Aufrufe billiger sind als permanent auf gekreuzte Pointer zu testen. Details folgen.

9 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur Wo die Gefahren lauern

Grunds¨atzlich sollte das Sortierprogramm mit jeder Art von Eingabe klar kommen, einschließlich Folgen der L¨ange null oder eins und Dateien mit Vorsortierung oder Duplikaten, das Ganze ohne Absturz oder Fehler in der Ausgabe. Recht h¨aufig kommt es zu einem Indexfehler (array access out of bounds).

10 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur Quadratische Degeneration

Selbst wenn das Programm nicht absturzt,¨ kann es zu einer Degeneration mit einer Laufzeit O(n2) kommen, weil in jedem Schleifendurchlauf nur ein Satz abgespalten wird. Das passiert z. B. bei bereits sortierter Eingabe, wenn als Pivotelement der erste oder letzte Schlussel¨ genommen wird. Dann w¨achst auch der Rekursionsstapel auf O(n) extra Platz, was unserer in situ Forderung widerspricht.

Degeneration zu vermeiden ist nicht leicht und h¨angt von der Pivotwahl und einer adaptiven Teilungsstrategie ab. Will man nur die Stapelh¨ohe auf logarithmische Gr¨oße beschr¨anken, genugt¨ es, immer die kurzere¨ Folge zuerst zu sortieren. Auch hierzu sp¨ater mehr.

11 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur Eine erste Implementierung

Hier kommt jetzt die Originalimplementierung in Pseudo-Pascal, wie sie damals in Turku pr¨asentiert wurde. Die Annahmen sind, dass ein Array a[0..N] zu sortieren ist, wobei a[0].key ein Stopper ist mit einem kunstlichen¨ Schlussel,¨ der kleiner als oder h¨ochstens gleich zu jedem Wert in der Folge a[1..N] ist, d. h.

a[0].key ≤ a[i].key ∀i (1 ≤ i ≤ N).

Der Stopper (engl. auch sentinel) vermeidet zus¨atzliche Abfragen auf Feldgrenzen. Das ist ein ublicher¨ Trick, den auch Knuth erw¨ahnt [Knu98, p. 4]. Der ¨außere Aufruf lautet dann Quicksort(s, 1, N) fur¨ eine gegebene Folge s mit N S¨atzen, d. h. die Parameter l und r referenzieren den ersten und letzten (echten) Satz im Array s. Die Folge s darf nicht leer sein, d. h. wir setzen N ≥ 1 voraus, was sich durch eine umhullende¨ Funktion (wrapper) sicherstellen ließe.

12 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur

Listing 3: Der originale Turku-Quicksort. procedure Q u i c k s o r t ( var a : sequence ; l , r : in teg er ); { call for a[1..N] and a[0].key ≤ a [ i ] . key ∀i (1 ≤ i ≤ N)} var H : keytype ; rt , lt : in teg er ; begin i f l + 1 < r { sequence size larger than 2} then begin lt := l − 1; rt := r; H := a[r].key { last key as pivot } while lt ≤ rt do begin repeat lt := lt + 1 u n t i l a[lt].key ≥ H ; repeat rt := rt − 1 u n t i l a[rt].key ≤ H ;

13 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur

s w i t c h (a[lt], a[rt]) end { w h i l e } s w i t c h (a[lt], a[rt] ) ; s w i t c h (a[lt], a[r] ); i f l < rt then Q u i c k s o r t (a, l, rt ); i f lt + 1 < r then Q u i c k s o r t (a, lt + 1, r ) end e l s e i f a[l].key > a[r].key then s w i t c h (a[l], a[r]) end { Q u i c k s o r t }

14 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur Kleine Anregung zum Knobeln

Ubung.¨ In dieser Implementierung tauchen zwei Tauschoperationen a[lt] :=: a[rt] und a[lt] :=: a[r] auf. Die erste korrigiert den fehlerhaften Tausch innerhalb der while-Schleife. Die zweite bringt das Pivot-Element in die Mitte. Da solche Tauschoperationen x :=: y mittels drei Zuweisungen aux := x; x := y; y := aux in den meisten Programmiersprachen implementiert werden, versuche man beide zusammen mit so wenig Zuweisungen wie m¨oglich zu programmieren.

15 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur Schwachstellen im Design

Das Design ist nicht sehr elegant. Der Rumpf der Prozedur beginnt mit einem Test l + 1 < r, der Folgen der L¨ange kleiner oder gleich 2 abf¨angt. Diese kurzen Folgen werden durch einen direkten Vergleich in die richtige Ordnung gebracht, falls n¨otig. Das funktioniert auch fur¨ l = r (Gr¨oße 1), was nur gebraucht wird, wenn Quicksort ursprunglich¨ mit einer Datei mit nur einem Satz aufgerufen wird. Wie oben gesagt, funktioniert die Prozedur fur¨ eine leere Datei nicht.

16 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur Kurze Restfolgen

Rekursive Aufrufe fur¨ Folgen der L¨ange 0 oder 1 werden im Prozedurrumpf durch Tests l < rt und lt + 1 < r vor den Aufrufen vermieden. Tests auf kurze Folgen vor den rekursiven Aufrufen und dann nochmal am Anfang der Prozedur ist reichlich seltsam. Der Grund ist, dass wir die Aufrufe fur¨ Folgen der L¨ange 0 oder 1 ganz vermeiden wollen, weil Prozeduraufrufe teuer sind.

Zweitens spielen kurze Folgen eine große Rolle – jeder Satz wird am Ende zur Unterfolge der L¨ange 1! Hoare hat schon in seiner Originalpublikation den Wechsel auf eine andere Sortiermethode fur¨ Unterfolgen der L¨ange 3 oder 4 vorgeschlagen [Hoa62, p. 11]. Sedgewick hat dann sp¨ater als Umschaltgrenze eher 9 oder 10 empfohlen [Sed78, p. 850], wobei der Trick auch darin besteht, die Unterdateien zun¨achst unbehandelt zu lassen und am Ende einmal die ganze Datei per Einfugesortierung¨ fertig zu stellen.

17 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur Spezialfall n = 2

Also ist der Test am Anfang der Prozedur nur die Spezialbehandlung fur¨ Folgen der L¨ange 2, die mit einem Vergleich zu erledigen sind. In einer optimierten Fassung wurden¨ wir l¨angere Folgen, z. B. kleiner als n = 11, unbehandelt lassen.

18 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur Die Hillmore-Verbesserung

 Publikationen zu Quicksort aus den sp¨aten Sechzigern erw¨ahnen oft eine sog. Hillmore-Verbesserung. Dies bezieht sich auf die Zertifizierung der Hoareschen Algorithmen 63, 64, und 65: Partition, Quicksort, Find in [Hoa61] durch J.S. Hillmore [Hil62].

Hillmore schl¨agt in einem Kommentar vor, die Rekursion fur¨ Unterfolgen der L¨ange 2 oder kurzer¨ abzubrechen – so wie wir das auch machen – und berichtet von einer Verbesserung um 4–5 Prozent bei der Anzahl der Schlusselvergleiche¨ und 25–30 Prozent bei der Anzahl der Prozeduraufrufe.

In derselben Ausgabe der Communications of the ACM ver¨offentlicht Robert W. Floyd das Sortierverfahren Treesort als Algorithmus 113 [Flo64].

19 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur Historische Anmerkung zu den ACM-Zertifizierungen I

 Das algorithmische Wissen in der Informatik sequentiell durchzunummerieren, kommt uns heute im Zeitalter des World Wide Web kurios vor. Der Versuch stammt aus dem Jahr 1960, als die Communications of the ACM ein neues Editorial mit dem Namen “Algorithms” einfuhrten¨ mit dem Ziel .. to publish algorithms consisting of “procedures” and programs in the Algol language.[Her60, p. 73] Die Ehre, den Algorithmus Nr. 1, genannt QUADI, beigesteuert zu haben, geht an R. J. Herbold und das Zitat stammt aus dem Vorwort zu dem Artikel. Fur¨ Beitr¨age waren drei Arten vorgesehen: Algorithmen, Zertifikate und Anmerkungen, letztere zu bereits ver¨offentlichten Algorithmen.

20 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur Historische Anmerkung zu den ACM-Zertifizierungen II

Die Idee scheint im Computation Laboratory des nationalen Standardisierungsburos¨ (National Bureau of Standards) in Washington D.C. geboren worden zu sein. Einreichungen konnten an J. H. Wegstein vom NBS geschickt werden. Die Idee war kuhn,¨ nicht zuletzt indem man Algol als bevorzugte Programmiersprache fur¨ die Algorithmen w¨ahlte. Altere¨ Leser werden sich vielleicht erinnern, dass zur damaligen Zeit IBM der beherrschende Lieferant fur¨ Rechnerausstattungen war und IBM hatte entschieden, dass dieses europ¨aische Kind Algol keine ernstzunehmende Sprache war.

21 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur Historische Anmerkung zu den ACM-Zertifizierungen III

Zertifizierungen durch andere Autoren wurden auch in den Communications ver¨offentlicht und besagten, dass der Algorithmus als Programm ordnungsgem¨aß zum Laufen gebracht wurde. Oft wurden dazu dann Laufzeitmessungen der Implementierungen in Fortran oder Algol mitangegeben. Hillmores Zertifikat zu den Quicksort Algorithmen enth¨alt den folgenden Satz: The body of the procedure find was corrected to read [... ] and the trio of procedures was then successfully run using the Elliott ALGOL translator on the National-Elliott 803. [Hil62, p. 439]

Den Algol Compiler fur¨ die 803 hatte niemand anderer als Tony Hoare selbst geschrieben, der damals im August 1960 von der britischen Firma Elliott Brothers als Programmierer eingestellt worden war [Wik13].

22 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur Die Ottmann&Widmayer-Variante

 Thomas Ottmann und Peter Widmayer pr¨asentieren in ihrem Algorithmen und Datenstrukturen Lehrbuch [TO12] eine sch¨onere Version des Wegnerschen Quicksort aus Turku (Listing 24). Th. Ottmann konnte sich dabei auf die Habilitationsschrift von Wegner in Karlsruhe beziehen, deren Erstgutachter er war, ganz ¨ahnlich wie sich D. E. Knuth auf Sedgewicks Doktorarbeit stutzt,¨ die er in Stanford betreute.

23 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur

Listing 4: Lehrbuch-Quicksort aus [TO12]. procedure q s o r t ( var a : sequence ; l , r : in teg er ); { for a[1..N] and a[0].key ≤ a [ i ] . key ∀i (1 ≤ i ≤ N)} var v , i , j : in teg er ; begin i f r > l { size greater 1} then begin i := l − 1; j := r; v := a[r].key { right key as pivot } while true do begin repeat i := i + 1 u n t i l a[i].key ≥ v ; repeat j := j − 1 u n t i l a[j].key ≤ v ; i f i ≥ j then break ; { i is pivot position } s w i t c h (a[i], a[j]) end ;

24 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur

s w i t c h (a[i], a[r] ); q s o r t (a, l, i − 1 ) ; q s o r t (a, i + 1, r ) end end

25 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur Singletons Beobachtung

In den Listings auf den Folien 6, 13 und 24 sieht man, dass die repeat-Schleifen auf Schlusseln¨ gr¨oßer bzw. kleiner oder gleich H anhalten. Warum bei Gleichheit stoppen?

Zum einen verhindert es, dass der linke Zeiger uber¨ das Pivotelement H hinausl¨auft, falls H der gr¨oßte Wert in der Datei ist, was regelm¨aßig der Fall ist, wenn die Datei schon sortiert vorliegt. Zum zweiten sorgt diese Maßnahme dafur,¨ dass bei Eingabe von Multimengen, speziell einer un¨aren oder bin¨aren Datei, die Teilung in der Mitte erfolgt und damit Degeneration vermieden wird. Der Preis dafur¨ sind uberfl¨ ussige¨ Vertauschungen. Dieser Vorschlag geht auf R. C. Singleton aus dem Jahr 1969 zuruck¨ [Sin69].

26 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur Lomutos Einwege-Quicksort

Bisher w¨ahlten die Programme den rechtesten (oder den linkesten) Schlussel¨ als Pivot. Das ist eine schlechte Wahl, da es dann zur Entartung mit einer Laufzeit O(n2) bei bereits sortierter Eingabe kommen kann. Verschiedene Autoren haben bessere Pivot-Auswahlstrategien empfohlen, die wir uns jetzt anschauen.

Wir fangen mit einer dritten einfachen Variante an, die als Lomutos Quicksort bekannt ist. Sie stammt aus den Programming Pearls, einer Serie die Jon Bentley regelm¨aßig in den CACM ver¨offentlichte, hier speziell das Aprilheft aus dem Jahr 1984 [Ben84]. Das Verfahren hat eine verfeinerte Pivot-Auswahl und andere interessante Eigenschaften. Der gezeigte Programmcode verwendet die ursprunglich¨ von Bentley gew¨ahlten Variablenbezeichner.

27 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur

Listing 5: Lomutos Quicksort aus [Ben84]. { sort array X[1..N], no sentinel element required } procedure QSort (L , U : in teg er ); var T : keytype ; I, LastLow : in teg er ; begin i f L < U { size greater 1} then begin swap (X[L], X[RandInt(L, U)] ); T := X[L] ; LastLow := L ; f o r I := L + 1 to U do { Invariant: X[L+1 .. LastLow] < T and X[LastLow+1 .. I −1] ≥ T} i f X[I] < T then

28 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur

begin LastLow := LastLow + 1 ; swap (X[LastLow], X[I]) end ; swap (X[L], X[LastLow] ); QSort (L, LastLow − 1 ) ; QSort (LastLow + 1, U ) end end

29 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur Pivotwahl I

Das Verfahren w¨ahlt ein zuf¨alliges Element aus der Folge als Pivot1. Dies wurde bereits von Hoare selbst im Ursprungsartikel vorgeschlagen [Hoa62, p.11]. Wie in anderen stochastischen Verfahren (engl. randomized algorithms), z. B. stochastischer Suche, ist die Aufteilungsposition im Mittel nahezu optimal und die Wahrscheinlichkeit einer Degeneration vernachl¨assigbar. Allerdings ist RandInt eine “teure” Funktion, daher kommt der Vermeidung von Rekursion fur¨ kurze Unterfolgen besondere Bedeutung zu.

1RandInt(L, U) liefert eine Pseudozufallszahl als Integer innerhalb der Grenzen [L..U]. 30 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur Pivotwahl II

Hoare hatte auch vorgeschlagen, das Pivotelement aus einer kleinen Stichprobe zu w¨ahlen, konnte aber m¨ogliche Vorteile nicht analytisch belegen. Sedgewick zeigt in [Sed77, Sed78], dass sich der Aufwand fur¨ eine gr¨oßere Stichprobe nicht auszahlt und schl¨agt die bekannte Median-von-drei-Strategie vor. Dabei werden die Schlussel¨ aus erster, mittlerer und letzter Position in der Datei zur Auswahl genommen. Auch diese median-of-three pivot selection geht auf Richard C. Singleton aus dem Jahr 1969 zuruck¨ [Sin69].

31 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur Einwege-Aufteilung

Ferner haben wir es bei Lomuto mit einem Einwege-Quicksort zu tun, d. h. die Teilephase durchk¨ammt die Folge nur in einer Richtung von links nach rechts (siehe Abb. 2). Alle S¨atze r mit r.key ≥ T bewegen sich wie in einem Rad (engl. wheel) nach rechts.

Der Begriff Rad (wheel) fur¨ eine Folge von S¨atzen, die dadurch bewegt wird, indem man den ersten (oder letzten) Satz ans Ende (den Anfang) der Folge tauscht, stammt aus einer Arbeit von Teuhola und Wegner zur Duplikatseliminierung mit minimalem zus¨atzlichen Platz und durchschnittlich linearer Zeit [TW91].

32 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur

T < T ≥ T ?

L LastLow I U

Abbildung 2: Einwege-Durchlauf mit Teilen&Tauschen

33 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur Wie viele Vertauschungen gibt es jetzt?

Die linke H¨alfte (S¨atze r mit r.key < T ) bewahrt die relative Eingabereihenfolge, d. h. die Aufteilung ist stabil (stable) im Sinne der Definitionen aus der Vorlesung 1. S¨atze mit gleichen Schlusseln,¨ die zum “Rad” angefugt¨ werden, verlieren dagegen ihre relative Eingabeordnung.

Zugleich ist leicht einzusehen, dass bei zuf¨alliger Eingabe ohne Duplikate, im Mittel die H¨alfte der Schlussel¨ kleiner und die andere H¨alfte gr¨oßer als das Pivotelement ist. Demnach werden im Mittel N/2 Austauschschritte gemacht. Frage: Sind das mehr als bei einem Quicksort mit Zweiwege-Teilungsphase? Antwort: Ja, sehr viel mehr! Auf Folie 8 wurden N/6 Vertauschungen genannt fur¨ Dateien in zuf¨alliger Anordnung2. 2Man beachte aber, dass wir im Moment internes Sortieren behandeln. Auf einer Platte kann die hohe Anzahl an Vertauschungen gunstiger¨ sein als eine Zweiwege-Aufteilung, bei der ein Zeiger sich entgegen der Rotationsrichtung bewegt. 34 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur Nochmal genauer auf die Vertauschungen geschaut I

 Die Behauptung, Lomutos Quicksort mache im Mittel N/2 Vertauschungen, beruhte auf Bentleys Argument, wonach [. .. ] after a typical partitioning of N elements, there are about N/2 elements above the partition value and N/2 elements below it. [Ben84, p. 288]

Tats¨achlich sind die Dinge etwas komplizierter.

35 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur Nochmal genauer auf die Vertauschungen geschaut II

Im klassischen Zweiwege-Quicksort sucht man zwei S¨atze, die der Ordnung widersprechen und vertauscht diese dann paarweise. In Lomutos Einwege-Quicksort sind die Vertauschungen einseitig bestimmt. Die Anzahl der Vertauschungen ist immer gleich der Anzahl der Schlussel¨ die unterhalb des Pivotelements liegen und damit gleich der L¨ange der linken Teilfolge. Außerdem kommt durch eine Vertauschung genau ein Satz in die richtige Teilfolge, der andere Satz, der an der Vertauschung beteiligt ist, war bereits in der richtigen Folge und tauscht lediglich den Platz.

Ist jetzt zuf¨allig die linke Teilfolge kurz, finden weniger als N/2 Vertauschungen statt, ist die Folge lang, wird es mehr als N/2 swaps geben. Da die L¨ange der linken Teilfolge gleichm¨aßig zwischen kurz und lang pendelt, gleicht sich dies im Mittel zu N/2 Vertauschungen aus.

36 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur Einfluss der Pivotwahl auf die Vertauschungen

Es ist eigentlich paradox, dass im klassischen Zweiwege-Quicksort eine raffinierte Pivotwahl die Anzahl der Vertauschungen je Teilephase erh¨oht. Gel¨ange es uns, die Folge immer genau in der Mitte zu teilen, dann h¨atten wir sogar N/4 Vertauschungen. Fur¨ die beinahe perfekte median-of-three pivot selection ergeben sich nach Sedgewick [Sed77] ungef¨ahr N/5 Vertauschungen. Fur¨ ein einzelnes, zuf¨allig gew¨ahltes Pivotelement sind es die bereits bekannten “nur” N/6 swaps, wie wir mit Hilfe von etwas Kombinatorik in der n¨achsten Vorlesung zeigen wollen.

Warum soll man nach einer guten Strategie fur¨ die Pivotwahl suchen, wenn man dadurch die Anzahl der Vertauschungen erh¨oht? Tatsache ist, dass eine eher h¨alftige Aufteilung die Anzahl der rekursiven Teilungsschritte stark reduziert. Das wiegt in der Summe das h¨ohere Datenvolumen je Teilungsphase bei weitem auf.

37 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur Literatur I

[Ben84] Jon Louis Bentley, How to sort, Commun. ACM 27 (1984), no. 4, 287–291. [Flo64] Robert W. Floyd, Algorithm 245: Treesort3, Commun. ACM 7 (1964), no. 12, 701. [Her60] R. J. Herbold, Algorithms: Quadi, Commun. ACM 3 (1960), no. 2, 74–. [Hil62] J. S. Hillmore, Certification of algorithms 63, 64, 65: Partition, quicksort, find, Commun. ACM 5 (1962), no. 8, 439–. [Hoa61] C. A. R. Hoare, Algorithms 63, 64, 65: partition, quicksort, find, Commun. ACM 4 (1961), no. 7, 321–322.

38 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur Literatur II

[Hoa62] , Quicksort, The Computer Journal 5:1 (1962), 10–15. [Knu98] Donald E. Knuth, The Art of Computer Programming. Vol. 3: Sorting and Searching, 2nd ed., vol. 3, Addison-Wesley, 1998. [Mer85] Susan M. Merrit, An inverted taxonomy of sorting algorithms, CACM 28, 1 (1985), 96–99. [Sed77] Robert Sedgewick, The analysis of quicksort programs, Acta Inf. 7 (1977), 327–355. [Sed78] , Implementing quicksort programs, Commun. ACM 21 (1978), no. 10, 847–857.

39 / 40 Der klassische Quicksort Lomutos Einwege-Quicksort Literatur Literatur III

[Sin69] Richard C. Singleton, Algorithm 347: an efficient algorithm for sorting with minimal storage, Commun. ACM 12 (1969), no. 3, 185–187. [TO12] Peter Widmayer Thomas Ottmann, Algorithmen und datenstrukturen, Spektrum Akademischer Verlag, 5. Aufl. 2012. [TW91] Jukka Teuhola and Lutz Michael Wegner, Minimal space, average linear time duplicate deletion, Commun. ACM 34 (1991), no. 3, 62–73. [Wik13] Wikipedia, Elliott 803 — wikipedia, the free encyclopedia, 2013, [Online; accessed 17-January-2013].

40 / 40 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern

Sortierverfahren Sedgewicks Analyse

Lutz Wegner

8. Mai 2014

1 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern Inhaltsverzeichnis

1 Sedgewicks Analyse Die Anzahl der Austauschschritte in der Teilephase Die durchschnittliche Anzahl von Schlusselvergleichen¨

2 Quicksort in den Sechzigern und Siebzigern Zusammenfassung der klassischen Resultate Der Fall Meansort

2 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern Die Anzahl der Austauschschritte in der Teilephase I

Die folgende Analyse zur Anzahl der Vertauschungen in der Teilephase beruht auf den Angaben in [Sed77, p. 333f]. Unter der Annahme einer zuf¨allig permutierten Eingabe ist das erste Element eine so gute Wahl wie jedes andere Element.

Wenn a[1] den k-kleinsten Schlussel¨ in der Datei hat, wie viele Schlussel¨ sind dann gr¨oßer als a[1].key in der Folge a[2], a[3],..., a[k]? Die Wahrscheinlichkeit, dass es t sind, ist ! ! N − k k − 1 t k − 1 − t A · B p(t) = ! = . N − 1 C k − 1

3 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern Die Anzahl der Austauschschritte in der Teilephase II

≤ a[1].key > a[1].key

1 2 k k + 1 N

| {z }| {z } k − 1 N − k Abbildung 1: Endordnung mit dem k-gr¨oßten Schlussel¨ als Pivot

4 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern Kleine Nachhilfe in Kombinatorik

Falls Ihre Kombinatorikkenntnisse auch so eingerostet sind wie meine, hier kommt eine kleine Hilfestellung.

C ist die Anzahl der Kombinationen (keine Ordnung) ohne Wiederholung von N − 1 Elementen zur k − 1-ten Klasse, was nichts anderes ist als die Anzahl der M¨oglichkeiten, k − 1 Elemente aus einer Menge von N − 1 Elementen auzuw¨ahlen. A ist die Anzahl der M¨oglichkeiten, t Elemente gr¨oßer als das Pivotelement unter N − k Elementen auszuw¨ahlen. Schließlich ist B die Anzahl der M¨oglichkeiten, die verbleibenden k − 1 − t Elemente, die kleiner oder gleich dem Pivot sind, aus k − 1 Elementen auszuw¨ahlen.

5 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern Bilde den Durchschnitt

Jetzt bilden wir den Durchschnitt, wobei das Pivotelement der k-gr¨oßte Schlussel¨ (1 ≤ k ≤ N) mit Wahrscheinlichkeit 1/N ist. Der Erwartungswert ergibt sich als Summe uber¨ alle t zu ! ! N − k k − 1 1 N k−1 t k − 1 − t E = X X t · . (1) N ! k=1 t=0 N − 1 k − 1

6 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern Vandermondesche Identit¨at

Die Doppelsumme sieht schrecklich aus, ist aber harmlos dank der sog. Vandermondeschen Identit¨at (Vandermonde’s convolution), ver¨offentlicht im Jahr 1772 und – laut Knuth [Knu68, p. 58] – schon in einer Abhandlung von Chu Shih-chieh aus dem Jahr 1303 erw¨ahnt: ! ! ! r s r + s X = integer n. k n − k n k

7 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern

Wir fangen damit an, den Nenner (engl. denominator) aus der letzten Summe zu ziehen, da er nicht von der Summationsvariablen t abh¨angt.

! ! 1 N 1 k−1 N − k k − 1 E = X X t N ! t k − 1 − t k=1 N − 1 t=0 k − 1 1 N 1 k−1 t (N − k)! (k − 1)! = X X N ! t! (N − k − t)! (k − 1 − t)! t! k=1 N − 1 t=0 k − 1 1 N 1 k−1 (N − k)! (k − 1) (k − 2)! = X X . N ! (N − k − t)! t! (k − 1 − t)! (t − 1)! k=1 N − 1 t=0 k − 1 (2)

8 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern

Entferne dann (k − 1) aus der letzten Summe, schreibe um in Binomialform

! ! 1 N k − 1 k−1 N − k k − 2 = X X (3) N ! t k − 1 − t k=1 N − 1 t=0 k − 1

9 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern

und wende jetzt die Vandermondesche Identit¨at an

! 1 N k − 1 N − 2 1 N (k − 1)(N − k) = X = X N ! k − 1 N N − 1 k=1 N − 1 k=1 k − 1 (4) 1 N = X (kN − k2 − N + k) N(N − 1) k=1 " # 1 N2(N + 1) N(N + 1)(2N + 1) N(N + 1) = − − N2 + N(N − 1) 2 6 2 1 3N(N + 1) − (N + 1)(2N + 1) − 6N + 3(N + 1) = · N − 1 6 N2 − 3N + 2 N − 2 = = . (5) 6(N − 1) 6

10 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern Die durchschnittliche Anzahl von Schlusselvergleichen¨

Die ubliche¨ Methode, ein Sortierverfahren, das mittels Schlusselvergleichen¨ die Ordnung herstellt, zu beurteilen, ist, die Anzahl der ben¨otigten Vergleiche im Mittel und ggf. fur¨ den schlechtesten Fall fur¨ eine Eingabe der L¨ange N zu z¨ahlen. Da Quicksort ein rekursiver Algorithmus ist, tritt bei der Analyse eine Rekursionsgleichung auf (engl. recurrence relation). Fur¨ die meisten Informatikstudierenden ist Quicksort die erste (und meistens einzige) Gelegenheit im Studium, mit dieser nutzlichen¨ Analyseform in Beruhrung¨ zu kommen.

11 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern

Nehmen wir an, die Anzahl der Schlusselvergleiche¨ zum Teilen einer Folge der L¨ange N sei N + 1 (zwei zus¨atzliche Vergleiche durch das Uberkreuzen¨ der Indizes). Ferner werde jeder Schlussel¨ gleich wahrscheinlich als Pivot gew¨ahlt, und somit ergeben sich alle L¨angen der Teilfolgen zwischen 0 und N − 1 mit 1 Wahrscheinlichkeit N . Wenigstens ein Satz wird abgespalten, und Teilfolgen der L¨ange 0 oder 1 werden nicht weiter behandelt. Dies ergibt die folgende Rekursionsgleichung:

1 N c¯(N) = N + 1 + X (c¯(s − 1) +c ¯(N − s)) , (6) N s=1

fur¨ N ≥ 2, c¯(0) =c ¯(1) = 0, und fur¨ N + 1 bekommen wir

1 N+1 c¯(N + 1) = N + 2 + X (c¯(s − 1) +c ¯(N + 1 − s)) . N + 1 s=1 (7)

12 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern

Der “Trick” besteht jetzt darin, die Gleichung (6) mit N und (7) mit N + 1 zu multiplizieren, was die Bruche¨ beseitigt, und dann (7) von (6) abzuziehen.

Nc¯(N) − (N + 1)¯c(N + 1) = N(N + 1) − (N + 1)(N + 2)+ N−1 N 2 X c¯(s) − 2 X c¯(s) (8) s=1 s=1 N + 2 c¯(N + 1) = (N + 2) − N + c¯(N) (9) N + 1 Da wir gerne eine geschlossene Formel fur¨ c¯(N) h¨atten, substituieren wir N fur¨ N + 1 mit dem Vorbehalt, dass sie jetzt nur fur¨ N ≥ 3 gultig¨ ist. Dann entrollen wir die Rekursionsgleichung ein wenig, bis man sieht, welche Reihen entstehen.

13 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern

N + 1 c¯(N) = 2 + c¯(N − 1) N N + 1  N  = 2 + 2 + c¯(N − 2) N N − 1 2(N + 1) N + 1  N − 1  = 2 + + 2 + c¯(N − 3) N N − 1 N − 2 2(N + 1) 2(N + 1) N + 1  4  = 2 + + + · ·· + 2 + c¯(2) N N − 1 4 3 (10)

und mit c¯(2) = 3 kommen wir zu

 1 1 1 = 2 + 2(N + 1) + + · ·· + + N + 1. (11) N N − 1 4

14 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern

In Gleichung (11) entdecken wir (mit drei fehlenden Elementen) die Reihe 1 1 1 n 1 + + · ·· + + 1 = X n n − 1 2 i i=1

die als n-te harmonische Zahl Hn bekannt ist (siehe Anhang im Skript zur Vorlesung).

15 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern Ergebnis der Analyse der Schlusselvergleiche¨ I

Somit haben wir am Ende  1 1  c¯(N) = 2 + 2(N + 1) H − − − 1 + N + 1 N 3 2

= 2(N + 1)HN − 8N/3 − 2/3 = 2(N + 1)(HN+1 − 4/3). (12)

Fur¨ die n-te harmonische Zahl Hn gibt es eine praktische Absch¨atzung, weil immer

ln n ≤ Hn ≤ ln n + 1.

16 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern Ergebnis der Analyse der Schlusselvergleiche¨ II

Die Analyse zeigt somit, dass Quicksort ohne Optimierungen eine Datei der Gr¨oße N mit N unterschiedlichen Werten in einer zuf¨alligen Anordnung mit rund 2N ln N Schlusselvergleichen¨ sortiert, was asymptotisch dasselbe ist wie O(N log N). Man beachte aber, dass in der Analyse vorausgesetzt wird, dass nach der Teilephase die S¨atze in den zwei (oder bei komplizierteren Varianten noch mehr) entstehenden Teilfolgen wiederum eine zuf¨allige Reihung haben.

17 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern Quicksort in den Sechzigern und Siebzigern

Tony Hoare erfand Quicksort im Jahr 1961. W¨ahrend der Sechziger erschienen mehrere Varianten, die Verbesserungen versprachen. Die genaue Analyse, inklusive der fur¨ Multimengen, stammt von Sedgewick aus den sp¨aten Siebzigern als Ergebnis seiner Doktorarbeit uber¨ Quicksort bei Donald Knuth.

18 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern Was um 1975 zu Quicksort bekannt war I

Die folgenden Aussagen fassen das zusammen, was gegen Mitte der Siebziger zu Quicksort bekannt war und empfohlen wurde. Unter ungunstigen¨ Umst¨anden kann Quicksort degenerieren. Die Laufzeitkomplexit¨at fur¨ den schlechtesten Fall ist daher 2 cmax (N) = O(N ). Die Durchschnittskomplexit¨at von Quicksort (Anzahl der Schlusselvergleiche¨ als Funktion der Eingabel¨ange) ist asymptotisch optimal und kann mittels der Rekursionsgleichung

1 N c¯(N) = {N − 1, N, N + 1} + X (c¯(s − 1) +c ¯(N − s)) N s=1

19 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern Was um 1975 zu Quicksort bekannt war II

fur¨ N ≥ 2 und c¯(0) =c ¯(1) = 0 berechnet werden. Bei Varianten, bei denen in der Teilephase N + 1 Vergleiche stattfinden, erh¨alt man dann 4 2(N + 1)(H − ) = O(N log N). N+1 3 Fur¨ die Pivotwahl mit einem Element aus einer zuf¨alligen Permutation ergeben sich N/6 Vertauschungen je Teilephase. Roger S. Scowen [Sco65] schlug ursprunglich¨ vor, statt einem zuf¨alligen Satz (wie von Hoare vorgesehen), den in der Mitte als Pivot zu w¨ahlen. Allerdings erreicht man eine deutlichere Verbesserung in der durchschnittlichen Laufzeit und einen besseren Schutz gegen Entartung durch die Median-von-drei-Auswahl des Pivotelements, wobei man den ersten, letzten und mittleren Satz nimmt.

20 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern Was um 1975 zu Quicksort bekannt war III

In der Teilephase sollte man auf S¨atzen mit ≤ und ≥ statt nur mit < und > anhalten und tauschen. Diese beiden letzten Empfehlungen gehen auf [Sin69] zuruck.¨ Die Rekursion sollte fur¨ kurze Teilfolgen abgebrochen werden. Diese Idee geht auch auf Scowen [Sco65] zuruck,¨ der seinen Algorithmus Quickersort nannte. Sedgewick [Sed77, Sed78] best¨atigte sp¨ater n = 11 als eine gute Abbruchgrenze und schlug einen einzigen Durchlauf des “Sortierens durch Einfugen”¨ ganz am Ende der Sortierung vor. Knuth [Knu98, p. 389] zitiert in der zweiten Auflage von Band 3 allerdings LaMarca und Ladner [LL97], die herausfanden, dass es in modernen Rechnern mit großen Cache-Speichern besser ist, sofort die kurzen Teilfolgen zu sortieren, statt bis zum Ende zu warten.

21 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern Was um 1975 zu Quicksort bekannt war IV Sortiert man die kurzere¨ Teilfolge zuerst, l¨asst sich dadurch der Rekursionsstapel auf eine Tiefe von h¨ochstens log2 N begrenzen [Sco65]. Da Quicksort ein klassischer Fall von tail recursion1 ist, kann der zweite rekursive Aufruf durch einen Sprung an den Anfang der Routine (und einige Variablenzuweisungen) ersetzt werden. Explizite rekursive Aufrufe k¨onnen insgesamt vermieden und durch einen selbstverwalteten Stapel ersetzt werden. Die Ersparnis ist gering und das Programm wird dadurch erheblich komplizierter. Die Idee geht auf Scowens Quickersort zuruck.¨ Bei den bisher pr¨asentierten Varianten darf man nicht auf eine Beschleunigung fur¨ Eingaben mit Vorsortierung oder Multimengeneigenschaft hoffen. 1Mit tail recursion bezeichnet man eine Funktion, die sich in der letzten Anweisung selbst wieder aufruft. 22 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern Der Vergleich durch Loeser 1974

Rudolf Loeser untersuchte 1974 in einem umfassenden Leistungsvergleich mehrere Quicksort-Varianten [Loe74], inklusive Quickersort von Scowen [Sco65], Qsort von van Emden [vE70b, vE70a], Hoares ursprunglichen¨ Algorithmus, Floyds Heapsort (Treesort3), und ein paar andere.

23 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern Van Emdens “Verbesserung” Qsort

Qsort ist eine von Marteen H. van Emden publizierte Quicksort-Optimierung. Er hatte auch das Laufzeitverhalten von Quicksort im Mittel untersucht [vE70b] und vorgeschlagen, ein Intervall [X, Z] als “Pivotelement” zu w¨ahlen, so dass nachher alle Schlussel¨ ≤ X in F1, alle Schlussel¨ ≥ Z in F2 sind. Das Intervall wird w¨ahrend der Teilephase verfeinert, und die Teilung endet mit einer Mitteldatei (einem Paar) {X, Z}. Der Algorithmus Qsort mit dieser Verbesserung wurde im Detail in [vE70a] aufgelistet. Van Emden zeigte dann, dass sich mit dieser Intervalltechnik die durchschnittliche Anzahl c¯ an Schlusselvergleichen¨ von Hoares ursprunglichen¨ 2N ln N ≈ 1, 386N log2 N auf ungef¨ahr 1, 140N log2 N reduzieren ließ. Loeser beobachtete dagegen aber einen Anstieg der gemessenen Laufzeit fur¨ Qsort im Vergleich zum ursprunglichen¨ Quicksort um etwa 50 Prozent!

24 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern Ein wenig Skepsis schadet nicht

Es ist sicher klug, eine gewisse Skepsis gegenuber¨ angeblich erheblichen Verbesserungen durch neue Quicksort-Varianten von Autoren zu bewahren, wenn man bedenkt, dass Anfang der Siebziger schon viele gute Versionen auf dem “Markt” waren. Robert Sedgewicks hochentwickelte Version [Sed78] (Corrigendum: CACM 22(6): 368 (1979)) mit Median-von-drei-Pivotwahl, Einfugesort¨ fur¨ kurze Teilfolgen der L¨ange M ≤ 9 und eigener Stapelverwaltung setzt dabei den Maßstab, gegen den man sich messen sollte. Aus eigenen Experimenten mit Zufallsfolgen und gewissen Sonderf¨allen kommt der Vortragende hier zum Schluss, dass ein “normaler” Quicksort (z. B. der originale Turku Quicksort aus der vorherigen Vorlesung) ungef¨ahr 10 Prozent langsamer l¨auft als Sedgewicks ultimative Empfehlung.

25 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern Verhandelt wird der Fall Meansort

1983 ver¨offentlichte Dalia Motzkin eine Quicksort-Variante, die sie Meansort nannte [Mot83]. Wie der Name andeutet, berechnet der Algorithmus den Pivotwert aus dem Mittel der Schlusselwerte¨ der zu teilenden Folge. Dazu wird die Summe gebildet und durch die Anzahl der Werte geteilt (siehe Abbildung 2).

< MEAN ? ≥ MEAN

i

if Ki < MEAN then {LEFT SUM ← LEFT SUM + Ki ; i ← i + 1} else . .. Abbildung 2: Aufsummieren der Schlussel¨ w¨ahrend der Teilephase

26 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern Fiktive Pivotwerte

Die Idee, mit einem “fiktiven Pivotwert” zu arbeiten, der gedacht zwischen zwei tats¨achlichen Schlusseln¨ liegt, ist nicht ganz neu. Knuth [Knu98, p. 128] berichtet im Band 3 seiner Buchserie TAoCP, dass John McCarthy schon fruh¨ vorschlug, (min + max)/2 als Pivot zu w¨ahlen, wobei der minimale und maximale Wert nebenbei (“on the fly”) ¨ahnlich wie in Meansort aufgesammelt wird. Genauso kann ein fiktives Element, das man z. B. aus (first + last)/2 berechnet, fur¨ Platten- oder Listensortierungen mit Quicksort nutzlich¨ sein, weil entweder die nachtr¨agliche Positionierung des Pivotelements in der Mitte einen zus¨atzlichen Lese-/Schreibzugriff erfordert oder weil man in einer Liste nicht auf ein Mittelelement fur¨ eine Median-von-drei-Pivotwahl zugreifen kann. Allerdings spricht nach der von Sedgewick durchgefuhrten¨ Analyse [Sed77] nichts dafur,¨ mehr als 2 bis 5 Werte als Grundlage fur¨ die Berechnung zu nehmen.

27 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern Motzkins Behauptung

Trotzdem schließt Motzkin ihren Beitrag mit einer starken Aussage bezuglich¨ der Qualit¨aten ihrer Modifikationen ab. Meansort is a considerable improvement over standard Quicksort. It has a better average behavior, the worst case occurs less often, and it is efficient in situations where there are repeating keys. Space requirements are minimal (as in most other versions of Quicksort) since the file is sorted in place, and the stack requirements are log2 N, provided that smaller subfiles are sorted first. This sort is not stable, but the Stable Quicksort [8] ([Mot81] note added in quote) technique may be applied here, if stability is needed. [Mot83, p. 251]

Im Listing ab Folie 29 zeigen wir den Algorithmus so, wie er in den Communications ver¨offentlicht wurde. Dort bezeichnen KI , KJ die Schlussel¨ der S¨atze RI , RJ . 28 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern

Listing 1: Meansort aus [Mot83] mit eingearbeiteten Korrekturen. PROCEDURE MEANSORT (M, N, MEAN) IF M < N THEN LEFT SUM ← 0 RIGHT SUM ← 0 I ← M J ← N LOOP WHILE KI < MEAN AND I 6= J DO LEFT SUM ← LEFT SUM + KI I ← I + 1 END WHILE WHILE KJ ≥ MEAN AND I 6= J DO RIGHT SUM ← RIGHT SUM + KJ I ← J − 1 END WHILE

29 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern

IF I 6= J THEN INTERCHANGE (RI , RJ ) ELSE EXIT LOOP ENDIF FOREVER IF I = M THEN RETURN ENDIF RIGHT SUM ← RIGHT SUM + KJ SUB FILE MEAN ← LEFT SUM /(I − M) CALL MEANSORT(M, I − 1, SUB FILE MEAN) SUB FILE MEAN ← RIGHT SUM/(N − J + 1) CALL MEANSORT(J, N, SUB FILE MEAN) ENDIF END OF PROCEDURE

30 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern Reaktionen

Die eher wagemutige Aussage von oben und mehrere typographische Fehler fuhrten¨ zu einer ganzen Reihe von Kommentaren. Die Herausgeberin der Computing Practices, damals Marie Jensen, entschloss sich, die als Korrespondenz eingereichten Beitr¨age nicht einzeln zu ver¨offentlichen, sondern Dalia Motzkin zu bitten, darauf zusammenfassend zu antworten. Diese Antwort erschien als Technical Correspondence im Juli 1984 [MK84].

31 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern Motzkins Antwort I

Die Technical Correspondence griff einige der offensichtlichen Schw¨achen auf. In der ersten Teilungsphase ist kein MEAN verfugbar;¨ Motzkin schl¨agt vor, mit

if Kfirst ≤ Klast then MEAN := Kfirst + 1 else MEAN := Klast

zu starten. Das Aufsummieren großer Integer kann zu einem Zahlenuberlauf¨ fuhren.¨ Das in der Arbeit ver¨offentlichte Programm l¨auft nicht fur¨ eine Datei F h2, 1i, sofern MEAN nicht vom Typ real ist. Die gemessene Anzahl an Schlusselvergleichen¨ war zu niedrig, weil die Vergleiche aus der ersten Teilungsphase fehlten.

32 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern Motzkins Antwort II

Diese Erwiderung enthielt auch eine uberarbeitete¨ Version MSort mit ge¨anderten Schleifen und neuen Tabellen fur¨ die Messungen, darunter auch ein Vergleich mit einem Median-von-drei-Quicksort, genannt SSort. Als Ergebnis des Vergleichs wird MSort eine 10-prozentige Uberlegenheit¨ gegenuber¨ SSort bescheinigt. Die Antwort enthielt jedoch keine Laufzeiten.

33 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern Wegners Variante von Meansort

In einer unver¨offentlichten Replik zur Originalarbeit von D. Motzkin in den Communications schl¨agt Wegner eine uberarbeitete¨ Pascal-Version von Meansort vor. Das Listing ab Folie 35 zeigt dieses Programm, wobei das Anhalten fur¨ kurze Teilfolgen weggelassen wurde. Fur¨ die erste Teilungsphase berechnet diese Variante einmal die Summe aller Schlussel¨ (ohne Vergleiche) und bestimmt daraus den Wert MEAN. Die Uberlegung¨ dafur¨ ist, dass wenn die pr¨azise Berechnung des Pivotelements angeblich so wichtig ist, dann sollte sie auch gleich in der ersten Teilung zur Anwendung kommen.

34 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern

Listing 2: Wegners uberarbeitete¨ Pascal-Version von Meansort [Mot83] procedure Meansort (left, right : i n d e x ) ; var k : i n d e x ; firstsum : keytype ; procedure MSort (el, r : i n d e x ; mean : keytype ) ; l a b e l 9 9 ; var ls, rs : keytype {sum left , resp. right subfile } ; i, j : i n d e x { pointer into file } ; begin i f el < r then begin { f i l e s i z e > 1} i := el; j := r; ls := 0; rs := 0 ; 9 9 : while a[i].key ≤ mean do begin ls := ls + a[i].key; i := i + 1 end ; while a[j].key > mean do

35 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern

begin rs := rs + a[j].key; j := j − 1 end ; i f i < j then begin { pointers have not crossed } ls := ls + a[j].key; rs := rs + a[i].key ; s w i t c h (a[i], a[j] ); i := i + 1; j := j − 1 ; goto 99 end ; i f i ≤ r then begin MSort (el, i − 1, ls div (i − el )); MSort (j + 1, r, rs div (r − j )) end end { f i l e s i z e > 1 − e l s e s k i p } end {MSort} ; begin { nonrecursive part of Meansort frame } firstsum := 0 ;

36 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern

f o r k := left to right do firstsum := firstsum + a[k].key ; a[right + 1] := firstsum { stopper in a[N+1]} ; MSort (left, right, firstsum div (right − left + 1 ) ) end ;

37 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern Abschlussurteil zu Meansort

L¨asst man diese Version von Meansort mit einem fur¨ kurze Teilfolgen der L¨ange M < 11 laufen, liegen die gemessenen Zeiten um ca. 30 Prozent h¨oher als bei einem vergleichbaren Quicksort. Andere ver¨offentlichte Versionen, etwa ein optimierter Meansort von Klaus Lagally und Bernhard Ziegler an der Universit¨at Stuttgart [LZ85], berichten von ¨ahnlichen Resultaten. Man darf daher mit Sicherheit behaupten, dass sich die aufw¨andige Pivotberechnung, die in Meansort vorgeschlagen wird, nicht auszahlt.

38 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern Literatur I

[Knu68] Donald E. Knuth, The art of computer programming, volume i: Fundamental algorithms, Addison-Wesley, 1968. [Knu98] , The Art of Computer Programming. Vol. 3: Sorting and Searching, 2nd ed., vol. 3, Addison-Wesley, 1998. [LL97] Anthony LaMarca and Richard E. Ladner, The influence of caches on the performance of sorting, Proceedings of the eighth annual ACM-SIAM symposium on Discrete algorithms (Philadelphia, PA, USA), SODA ’97, Society for Industrial and Applied Mathematics, 1997, pp. 370–379. [Loe74] Rudolf Loeser, Some performance tests of “quicksort” and descendants, Commun. ACM 17 (1974), no. 3, 143–152.

39 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern Literatur II

[LZ85] Klaus Lagally and Bernhard Ziegler, Optimized meansort: Omsort, Tech. Report 3, Institut fur¨ Informatik der Universit¨at Stuttgart, 1985. [MK84] Dalia Motzkin and John Kapenga, Technical correspondence: More about meansort, Commun. ACM 27 (1984), no. 7, 719–722. [Mot81] D. Motzkin, A stable quicksort, Softw. Practice and Experience 11 (1981), 607–611. [Mot83] Dalia Motzkin, Meansort, Commun. ACM 26 (1983), no. 4, 250–251. [Sco65] Roger S. Scowen, Algorithm 271: quickersort, Commun. ACM 8 (1965), no. 11, 669–670.

40 / 41 Sedgewicks Analyse Quicksort in den Sechzigern und Siebzigern Literatur III

[Sed77] Robert Sedgewick, The analysis of quicksort programs, Acta Inf. 7 (1977), 327–355. [Sed78] , Implementing quicksort programs, Commun. ACM 21 (1978), no. 10, 847–857. [Sin69] Richard C. Singleton, Algorithm 347: an efficient algorithm for sorting with minimal storage, Commun. ACM 12 (1969), no. 3, 185–187. [vE70a] Maarten H. van Emden, Algorithms 402: Increasing the efficiency of quicksort, Commun. ACM 13 (1970), no. 11, 693–694. [vE70b] , Increasing the efficiency of quicksort, Commun. ACM 13 (1970), no. 9, 563–567.

41 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen

Sortierverfahren Quicksort fur¨ verkettete Listen

Lutz Wegner

15. Mai 2014

1 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Inhaltsverzeichnis

1 Stabilit¨at und Beschleunigung fur¨ Multimengen Das klassische Sortierproblem versus Multimengen Stabilit¨at Beschleunigung – Smoothness Sortieren global betrachtet bezuglich¨ Beschleunigung und Stabilit¨at

2 Eine L¨osung fur¨ verkettete Listen TRISORT – Ein Dreiwege-Quicksort fur¨ verkettete Listen Eine Multimengenanalyse von TRISORT Die Tricks von Sedgewick und Burge Sedgewicks untere Schranke

2 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Sortieren und Multimengen

Wie in der ersten Vorlesung erw¨ahnt, besteht die Sortieraufgabe darin, N S¨atze (Schlussel)¨ in aufsteigende (oder absteigende) Ordnung mittels paarweiser Schlusselvergleiche¨ zu bringen. Oft bilden die Schlussel¨ eine Multimenge, wie etwa in der Tabelle unten, die einem Flugreservierungssystem ¨ahnelt.

3 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Sortieren der Passagiertabelle nach Flugnummer

Name Flight# Adams 265 Flight# Name Arnold 107 107 Arnold Atkins 911 107 Baldwin Baldwin 107 107 Byron . . Bell 699 . . sort Burns 265 265 Adams =⇒ Byron 107 265 Burns Key = Flight# Carter 480 265 Chou Chou 265 . . . . Davis 699 . . . .

4 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Stabilit¨at

Das Sortieren von Multimengen bringt zwei Besonderheiten mit sich: Stabilit¨at (stability) und Beschleunigung (smoothness) (vgl. die Definitionen in Vorlesung 1).

Stabilit¨at ist unproblematisch, wenn mit extra Platz gearbeitet wird, wie z. B. beim klassischen Mergesort. Wenn kein extra Platz (oder nur wenig) vorgesehen ist, wie beim Quicksort oder Heapsort, werden die Dinge komplizierter. In der Tat sind sowohl Quicksort, in der Array-Version, als auch Heapsort nicht stabil, d. h. gleiche Schlussel¨ behalten nicht ihre relative Eingabereihenfolge. Die Frage nach m¨oglicher Beschleunigung wird weiter unten behandelt.

5 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Stabilit¨at – ein altes, hartn¨ackiges Problem

 Stabiles, in situ Sortieren war schon immer eine Herausforderung. Knuth formuliert es als Ubungsaufgabe¨ in der ersten Auflage seines Bands 3 von TAoCP [Knu73, p. 388]. (Stable sorting in minimum storage.) A is said to require minimum storage if it uses only O((log N)2) bits of memory space for its variables besides the space needed to store the N records. [... ]

Design a stable minimum-storage sorting algorithm which requires only O(N(log N)2) units of time in its worst case. [Hint: It is possible to do stable minimum-storage merging in O(N log N) units of time.]

6 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Knuth verweist auf Vincent Pratt und Luis Trabb Pardo

In den Antworten zu den Ubungsaufgaben¨ nennt Knuth in der ersten Auflage [Knu73, p. 665] eine L¨osung fur¨ stabiles Mischen mit minimalem Platz (stable minimum-storage merging), die auf Vincent Pratt zuruckgeht¨ und zitiert die Arbeit von Luis Trabb Pardo [Par77] mit den Worten . .. the best possible answer to this problem: It is possible to do stable merging in O(n) time and stable sorting in O(n log n) time, using only O(log n) bits of auxiliary memory for a fixed number of index variables.

7 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Weitere Ergebnisse in Sachen Stabilit¨at

In der zweiten Auflage fugt¨ Knuth [Knu98, p. 701f] dem L. Trabb Pardo Resultat [Par77] Versionen mit verbesserten Konstanten hinzu, die von B.-C. Huang und M. A. Langston [HL92] stammen und erw¨ahnt einen weiteren Algorithmus von Antonios Symvonis fur¨ stabiles, in situ Mischen von M S¨atzen mit N S¨atzen, wenn M sehr viel kleiner ist als N [Sym95].

Wir kommen, wenn es die Zeit erlaubt, in der letzten Vorlesung auf die L¨osung von V. Pratt und den Trabb-Pardo-Algorithmus zuruck,¨ wenn wir generell Mischen zweier Folgen ohne zus¨atzlichen Platz betrachten.

8 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Rivest, Preparata und Dudzinski & Dydek I

In der Turku Lecture wurden noch drei andere stabile, minimum storage Sortierverfahren erw¨ahnt, obwohl die Auswahl eher willkurlich¨ war. Ronald L. Rivest [Riv73] pr¨asentiert 1973 einen schnellen, stabilen Algorithmus mit minimalem Zusatzplatzbedarf. Die Laufzeit im Durchschnitt ist O(N(log N)2), aber noch O(N2) im schlechtesten Fall. Franco P. Preparata [Pre75] liefert 1975 einen schnellen, stabilen Sortieralgorithmus mit absolut minimalem Zusatzplatz, wobei “absolut minimal” definiert ist als O(log N) extra Bits. Die durchschnittliche Laufzeit ist wieder O(N(log N)2).

9 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Rivest, Preparata und Dudzinski & Dydek II

Dudzinski und Dydek zeigen 1980 einen Algorithmus fur¨ stabiles Mischen [DD81], der fur¨ das Mischen zweier Vektoren der L¨angen M und N (M ≤ N) O(M log(N/M + 1)) Vergleiche und O((M + N) log M) Zuweisungen bei O(log M) Zusatzplatz ben¨otigt. Wir ubergehen¨ die Besprechung hier, weil die Verfahren mehr mit stabilem Mischen am Ort zu tun haben als mit Quicksort.

10 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Ein stabiler Quicksort auf verketteten Listen

Dalia Motzkin war die Erste, die 1981 feststellte, dass die Anwendung von Quicksort auf verkettete Listen ein stabiles Sortierverfahren mit einer Laufzeit von O(N log N) Schritten im Mittel liefert [Mot81]. Wegner [Weg82] schlug unabh¨angig davon eine Quicksort-Variante fur¨ verkettete Listen vor und verband damit eine Drei-Wege-Aufteilung (three-way split), die verhindert, dass Schlussel,¨ die gleich dem Pivotelement sind, in die Rekursion eingehen. Dies fuhrt¨ zu einem Quicksort mit einer durchschnittlichen Laufzeit von O(N log n), wobei N die Anzahl der S¨atze insgesamt und n die Anzahl der paarweise verschiedenen Schlusselwerte¨ darunter ist (1 ≤ n ≤ N). Naturlich¨ darf man Sortierverfahren, die auf verketteten Listen arbeiten, nicht in einen Topf werfen mit solchen, die im Hauptspeicher fur¨ Eingabedaten in einem Array gedacht sind.

11 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Sedgewicks Aussage zum Fehlen effizienter Methoden I

Bezogen auf “Smoothness” fur¨ eine Eingabe in einem Array stellen wir fest, dass Quicksort bisher Folgen gleicher Schlussel¨ nicht ausnutzen kann und sogar – noch schlimmer – mit einer Laufzeit von O(N2) degeneriert.

Das gilt auch fur¨ Vorsortierungen, von denen Quicksort nicht profitiert, sondern die auch wieder ein Risiko fur¨ Degeneration darstellen. Sedgewick fasst das in seiner grundlegenden Analyse von Quicksort fur¨ gleiche Schlussel¨ wie folgt zusammen [Sed77, p. 244]:

12 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Sedgewicks Aussage zum Fehlen effizienter Methoden II

Now, if we wish to use Quicksort to sort a file containing equal keys, we must decide how to treat keys equal to the partitioning element during the partitioning process. Ideally, we would like to get all of them into position in the file, with all the keys with a smaller value to their left, and all the keys with a larger value to their right. Unfortunately, no efficient method for doing so has yet been devised, so we shall have some keys equal to the partitioning element in the left subfile and some in the right. Im Folgenden werden wir argumentieren, dass es sehr wohl effiziente Methoden dafur¨ gibt, sowohl fur¨ verkettete Listen [Weg82, Weg83] als auch bei wahlfreiem Zugriff auf alle Elemente (Arrays) [Weg85].

13 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Globale Betrachtung bzgl. Smoothness und Stability

Eine sehr grobe Klassifizierung fur¨ Sortierverfahren in den fruhen¨ Achtzigern findet sich in der folgenden Tabelle. Dort sind Mergesort, Heapsort und Quicksort die klassischen Lehrbuchvarianten. Ein Haken (tick) in Klammern in der Spalte presorted deutet teilweise Erfullung¨ an, da die Algorithmen zus¨atzliche “Kniffe” brauchen, um von Vorsortierung zu profitieren.

14 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Die etwas exotischeren Wettbewerber

Die Tabelle enth¨alt auch andere bemerkenswerte L¨osungen fur¨ Beschleunigung bei Vorsortierung, darunter ein Algorithmus von C. R. Cook und Do Jiu Kim fur¨ nahezu sortierte Listen [CK80]1 und Edsger W. Dijkstras Smoothsort [Dij82]. Trabb Pardo steht fur¨ die Klasse der Verfahren, die auf stabilem, in situ Mischen beruhen. Die letzten zwei Reihen repr¨asentieren eine Klasse von Quicksort-Varianten, die fur¨ Beschleunigung konditioniert wurden (vgl. [Weg83, Weg85]).

1In dem Artikel geben Cook und Kim ihrem Hybridverfahren keinen Eigennamen, sondern nennen es einfach New Sorting Algorithm. Sie beschreiben es als eine Kombination von Quickersort [Sco65] und Sortieren durch Einfugen¨ mit Mischen [CK80, p. 622]. 15 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Ub¨ ersicht zum Stand der Kunst in den Achtzigern

Smooth on Multisets Presorted Stable In Situ √ √ Mergesort – ( ) – √ Quicksort – – – √ Heapsort – – – √ √ Trabb Pardo [Par77] – – √ √ √ Smoothsort [Dij82] – √ √ Cook + Kim [CK80] – – √ √ √ √ Linked List Quicksort ( ) √ √ √ Smooth Array Quicksort ( ) –

16 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Auftritt Trisort

Wie zuvor angemerkt, war Dalia Motzkin [Mot81] die erste Person, die feststellte, dass Quicksort ein stabiles Verhalten fur¨ einfach verkettete Listen zeigt. Sie analysierte das Verfahren aber nicht und schlug auch keine Dreiwegeaufteilung (<, =, >) vor.

Unabh¨angig davon pr¨asentierte Wegner [Weg82] eine Quicksort-Variante fur¨ das Sortieren einer verketteten linearen Liste. Dieses Verfahren enthielt eine solche Dreiwegeteilung, garantiert Stabilit¨at und verspricht Beschleunigung. Er analysierte das Verfahren auch und nannte es Trisort.

17 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Trisort graphisch

? ?

L1 < < ...

LH = = ...

L2 > > > ...

Abbildung 1: TRISORT – unidirektional mit Dreiwegeteilung nach [Weg82].

18 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Letzter Satz als Pivotelement und Stopper

Offensichtlich ist Trisort stabil und nimmt alle S¨atze mit einem Schlusselwert¨ gleich dem Pivotelement aus der Rekursion heraus. Wegner schl¨agt als Pivotelement den letzten Satz vor, weil man dann den Test fur¨ “letzter Satz?” nur machen muss, wenn ki = H erfullt¨ ist, d. h. der letzte Satz dient auch als Stopper. Die eigentliche Implementierung in Pascal ist nicht so hubsch,¨ haupts¨achlich weil die Listenbehandlung mit expliziten Pointern so unelegant ist.

19 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen

Listing 1: Hauptschleife fur¨ das Zusammenfugen¨ der Folgen am Ort. procedure TRISORT ( var first, last : r e f ) ; { linked list from first to last } {3 global dummy nodes sl, sh, sr } var sfl, sfr, sfh, lt, rt, ht, p : r e f ; H : keytype ; begin i f first <> last {|L| > 1} then begin lt := sl; rt := sr; ht := sh; sh ↑ .next := first ; p := sh; H := last ↑ .key { P i v o t = l a s t } ; repeat { terminates with p = last} p := p ↑ .next ; i f p ↑ .key < H then

20 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen

repeat { node goes to L1 } lt ↑ .next := p; lt := p; p := p ↑ .next u n t i l p ↑ .key >= H; { node 9 L1 } while p ↑ .key > H do begin { node goes to L2 } rt ↑ .next := p; rt := p; p := p ↑ .next ; i f p ↑ .key < H then repeat { node goes to L1 } lt ↑ .next := p; lt := p; p := p ↑ .next u n t i l p ↑ .key >= H; { node 9 L1 } end { w h i l e ; post−condition: p ↑ .key = H } ; ht ↑ .next := p; ht := p u n t i l p = last { list partitioned } ; sfl := sl ↑ .next; sfr := sr ↑ .next; sfh := sh ↑ .next { pointers to start of lists } i f lt <> sl

21 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen

then begin {L1 not empty} TRISORT (sfl, lt ); first := sfl; lt ↑ .next := sfh end { o f s o r t i n g L1 and relinking to LH } e l s e first := sfh ; { i f L1 empty, start with LH } i f rt <> sr then begin {sub− l i s t L2 not empty} TRISORT (sfr, rt ); ht ↑ .next := sfr; last := rt ; { l i n k LH to L2 } last ↑ .next := n i l { last node points to nil } end { o f s o r t i n g L2 } end {|L| > 1} end {TRISORT} ;

22 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Eine Multimengenanalyse von Trisort

Fur¨ die Analyse der Dreiwegeaufteilung von Quicksort k¨onnen wir auf die grundlegende Forschung von Sedgewick uber¨ “Quicksort with Equal Keys” [Sed77] zuruckgreifen.¨

Ohne Einschr¨ankung der Allgemeinheit sortieren wir die ganzen Zahlen 1,..., n. Im Fall einer Multimenge S = {x1 · 1, x2 · 2,..., xn · n} als Eingabe tritt die Zahl i gerade xi -mal auf mit x1 + x2 + ... + xn = N. Spezialf¨alle. n = N keine Duplikate n = 2 eine bin¨are Datei n = 1 eine un¨are Datei N x = M = ∀ 1 ≤ i ≤ n konst. Wiederholungsfaktor M i n

23 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Kombinatorik ist die Kunst des richtigen Z¨ahlens

Nach Definition ist eine Datei F zuf¨allig angeordnet, wenn jede der ! N N! = x1, x2,..., xn x1!x2! . .. xn!

Permutationen der Eingabezahlen gleich wahrscheinlich ist.

Wenn wir bin¨are Pascal-Vergleiche statt tern¨are MIX-Vergleiche z¨ahlen wollen, stellen wir fur¨ Trisort fest, dass es genau

1 Schlusselvergleich¨ ∀ ki < H, 2 Schlusselvergleiche¨ ∀ ki ≥ H und 1 Zeigervergleich ∀ ki = H gibt.

24 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Durchschnittliche Anzahl an Schlusselvergleichen¨

Daher ist die durchschnittliche Anzahl an Schlusselvergleichen¨ gegeben durch

1 c¯ (x ,..., x ) = X x (1 · (x + . .. + x ) + 2 · (x + ... + x )) 1 n N i 1 i−1 i n 1≤i≤n 1 + X x (c¯ (x ,..., x ) +c ¯ (x ,..., x )) N i 1 i−1 i+1 n 1≤i≤n (1)

mit c¯(x) = 2x. Daraus wird

x x c¯(x ,..., x ) = X 2x + 3 X k i (2) 1 n i x + . .. + x 1≤i≤n 1≤k

25 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Worauf wir hinauswollen

Die F¨alle mit einem konstanten Wiederholungsfaktor sind die aufschlussreichsten fur¨ einen Vergleich.

Trisort mit Pascal-Vergleichen 3(N + M)Hn − 4N untere Schranke mit MIX-Vergleichen 2(N + M)Hn − 3N − n Mit anderen Worten, Trisort erreicht die untere Schranke fur¨ Quicksort-Programme auf Multimengen, wie wir zeigen werden. Damit wir dahin kommen, brauchen wir etwas Mathematik, speziell Rekursionsgleichungen mit Multinomialkoeffizienten.

26 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Rekursionsgleichungen mit Multinomialkoeffizienten I

Die folgenden Techniken zur L¨osung von Rekursionsgleichungen mit Multinomialkoeffizienten stammen von Sedgewick und von Burge [Sed77, Bur76]. Man multipliziert zun¨achst die Rekursionsgleichung (1) mit N.

X   N · c¯ (x1,..., xn) = xi 1 · (x1 + ... + xi−1) + 2 · (xi + ... + xn) 1≤i≤n X   + xi c¯(x1,..., xi−1) +c ¯(xi+1,..., xn) 1≤i≤n (3)

27 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Rekursionsgleichungen mit Multinomialkoeffizienten II

Jetzt nimmt man die gleiche Formel fur¨ x2,..., xn.

X   (N − x1)¯c (x2,..., xn) = xi 1 · (x2 + ... + xi−1) + 2 · (...) 2≤i≤n X   + xi c¯(x2,... xi−1) +c ¯(...) 2≤i≤n (4)

28 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Rekursionsgleichungen mit Multinomialkoeffizienten III

Subtrahiere (4) von (3).

Nc¯(x1,..., xn) − (N − x1)c ¯ (x2,..., xn) = X 2 3x1 xi − x1 + x1 c¯(x2,..., xn) 1≤i≤n X   + xi c¯(x1,..., xi−1) − c¯(x2,..., xi−1) 2≤i≤n (5)

29 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Rekursionsgleichungen mit Multinomialkoeffizienten IV

Substituiere G(x1, ..., xn) fur¨ c¯(x1,..., xn) − c¯(x2,..., xn) und verkleinere wieder die Laufgrenzen, diesmal zu G(x1,..., xn−1).

X 2 N · G(x1,..., xn) = 3x1 xi − x1 1≤i≤n X + xi G(x1,..., xi−1) (6) 2≤i≤n X 2 (N − xn)G(x1,..., xn−1) = 3x1 xi − x1 1≤i≤n−1 X + xi G(x1,..., xi−1) (7) 2≤i≤n−1

30 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Rekursionsgleichungen mit Multinomialkoeffizienten V

Subtrahiere (7) von (6) und bilde die Teleskopsummen der rechten Seiten.

3x1 · xn G(x1,..., xn) = G(x1,..., xn−1) + x1 + . .. + xn 3x1xn−1 3x1xn = G(x1,..., xn−2) + + x1 + . .. + xn−1 x1 + . .. + xn . . 3x x = G(x ) + X 1 i (8) 1 x + . .. + x 2≤i≤n 1 i

31 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Rekursionsgleichungen mit Multinomialkoeffizienten VI

Resubstituiere jetzt:

x x c¯(x ,..., x ) =c ¯(x ,..., x ) +c ¯(x ) + 3 X 1 i 1 n 2 n 1 x + . .. + x 2≤i≤n 1 i

=c ¯(x3,..., xn) +c ¯(x2) + x x + 3 X 2 i +c ¯(x ) + 3 X ... x + . .. + x 1 3≤i≤n 2 i 2≤i≤n x x = X c¯(x ) + 3 X k i (9) i x + . .. + x 1≤i≤n 1≤k

32 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Spezialfall konstanter Wiederholungsfaktor

Das ist das Resultat (2) von oben. Obwohl pr¨azise, ist es wenig aufschlussreich. Wir k¨onnen es aber mit der unteren Schranke vergleichen, die Sedgewick fur¨ Quicksort auf Multimengen angibt (siehe die Besprechung ab Folie 35 unten). Betrachten wir fur¨ den Moment wieder den Spezialfall N/n = M = xi ∀i.

M2 c¯(n · M) = 2n · M + 3 X (i − k + 1)M 1 = 2n · M + 3M X X i − k + 1 1≤k≤n−1 k+1≤i≤n 1 = 2nM + 3M X X (10) (i + k) − k + 1 1≤k≤n−1 1≤i≤n−k | {z } i+1

33 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Lange Rechnung, kompaktes Resultat

Der “Trick” besteht hier darin, den Index von i = k + 1,..., n nach i = 1,..., n − k zu verschieben. Mit ein wenig Hilfe aus Anhang A in der Turku-Vorlesung bezuglich¨ harmonischer Zahlen Hn bekommen wir das Trisort-Resultat fur¨ Pascal-Vergleiche von Folie 26. X c¯(n · M) = 2nM + 3M (Hn−k+1 − 1) 1≤k≤n−1  X  = ... = 2nM + 3M Hi − n (11) 1≤i≤n

= 3(N + M)Hn − 4N (12)

Hinweis: Die Originalver¨offentlichung von Wegner [Weg82] enthielt einen Druckfehler in Gleichung (11).

34 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Sedgewicks untere Schranke

Die Kunst in der algorithmischen Komplexit¨atstheorie liegt nicht nur darin, die Leistungsf¨ahigkeit einer gegebenen L¨osung fur¨ ein allgemeines Problem, hier das Sortieren, zu analysieren, sondern fur¨ das Problem eine untere Schranke anzugeben, die kein Algorithmus, der auf einem vernunftigen¨ Rechenmodell beruht, unterbieten kann. Mit diesem Ziel definiert Sedgewick die Klasse der Quicksort-Programme [Sed77, p. 244]: Ein Programm heißt Quicksort-Programm, wenn es - eine Datei in drei Unterdateien aufspaltet, mit [... ], - ein Element fur¨ die Pivotauswahl heranzieht, - zwei zuf¨allig geordnete Teilfolgen aus einer gegebenen zuf¨alligen Teilfolge erzeugt. Beobachtung: Die Quicksort-Programme fur¨ verkettete Listen, z. B. Trisort, sind Quicksort-Programme nach obiger Definition.

35 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Wie gut ist TRISORT?

Q: Wie gut ist Trisort? A: Trisort ist optimal! Die Antwort folgt aus der unteren Schranke, die Sedgewick in [Sed77] angibt. Er beweist, dass jeder Quicksort wenigstens

1   c¯(x ,..., x ) = N − 1 + X x c¯(x , ..., x ) +c ¯(x ,..., x ) 1 n N j 1 j−1 j+1 n 1≤j≤n (13) Vergleiche im Mittel ben¨otigt, um eine Eingabedatei mit einer Multimenge S = {x1 · 1, x2 · 2,..., xn · n} zu sortieren. Als Teleskopsumme ergibt das

2x x G(x ,..., x ) = G(x ) + X 1 i (14) 1 n 1 x + . .. + x 2≤i≤n 1 i

36 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen MIX- versus Pascal-Vergleiche – warum so kleinlich?

In der Tat ist der einzige Unterschied zu Gleichung (8) eine 2 im Resultat versus einer 3 in unserer Analyse. Das liegt daran, dass Sedgewick Dreiwegevergleiche in MIX z¨ahlt, w¨ahrend wir mit Zweiwegevergleichen in Pascal arbeiten, wie schon auf Folie 26 erw¨ahnt.

Warum sind wir so kleinlich im Z¨ahlen der Pascal-Vergleiche und bei den Konstanten, die damit einhergehen? Es stellt sich heraus, dass man sich auch andere Strategien ausdenken kann, um die Sortierung fur¨ Multimengen oder vorsortierte Teilfolgen zu beschleunigen. Das ist das Thema der n¨achsten Vorlesung.

37 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Literatur I

[Bur76] William H. Burge, An analysis of binary search trees formed from sequences of nondistinct keys, J. ACM 23 (1976), no. 3, 451–454. [CK80] C.R. Cook and D.J. Kim, Best sorting algorithms for nearly sorted lists, Communications of the ACM 23:11 23 (1980), 620–624. [DD81] Krzysztof Dudzinski and Andrzej Dydek, On a stable minimum storage merging algorithm, Inf. Process. Lett. 12 (1981), no. 1, 5–8. [Dij82] Edsger W. Dijkstra, Smoothsort, an alternative for sorting in situ, Sci. Comput. Program. 1 (1982), no. 3, 223–233.

38 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Literatur II

[HL92] Bing-Chao Huang and Michael A. Langston, Fast stable merging and sorting in constant extra space, Comput. J. 35 (1992), no. 6, 643–650. [Knu73] Donald E. Knuth, The Art of Computer Programming, Volume III: Sorting and Searching, Addison-Wesley, 1973. [Knu98] , The Art of Computer Programming. Vol. 3: Sorting and Searching, 2nd ed., vol. 3, Addison-Wesley, 1998. [Mot81] D. Motzkin, A stable quicksort, Softw. Practice and Experience 11 (1981), 607–611. [Par77] Luis Trabb Pardo, Stable sorting and merging with optimal space and time bounds, SIAM J. Comput. 6 (1977), no. 2, 351–372.

39 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Literatur III

[Pre75] Franco P. Preparata, A fast stable sorting algorithm with absolutely minimum storage, Theor. Comput. Sci. 1 (1975), no. 2, 185–190. [Riv73] R.L. Rivest, A fast stable minimum-storage sorting algorithm, Tech. report, IRIA, 1973. [Sco65] Roger S. Scowen, Algorithm 271: quickersort, Commun. ACM 8 (1965), no. 11, 669–670. [Sed77] R. Sedgewick, Quicksort with equal keys, SIAM J Comput 6, No. 2 (1977), 240–267. [Sym95] Antonios Symvonis, Optimal stable merging, Comput. J. 38 (1995), no. 8, 681–690.

40 / 41 Stabilit¨at und Beschleunigung fur¨ Multimengen Eine L¨osung fur¨ verkettete Listen Literatur IV

[Weg82] Lutz Wegner, Sorting a linkes list with equal keys, IPL 15,5 (1982), 205–209. [Weg83] , The linksort family-design and analysis of fast, stable quicksort derivatives, Tech. Report Report 123, Institut fur¨ Angewandte Informatik und Formale Beschreibungsverfahren, Universit¨at Karlsruhe, 1983. [Weg85] , Quicksort for equal keys, IEEE TC C-34 No. 4 (1985), 362–367.

41 / 41 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien

Sortierverfahren Quicksort-Varianten mit Zwei- und Dreiteilung fur¨ verkettete Listen und Arrays

Lutz Wegner

22. Mai 2014

1 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Inhaltsverzeichnis

1 Quicksort fur¨ Multimengen in verketteten Listen MIX- versus PASCAL-Vergleiche Vorstellung LINKSORT Die Analyse von LINKSORT 2 Quicksort fur¨ Multimengen auf Arrays Funf¨ Wege zur Beschleunigung SLIDESORT HEAD&TAIL-SORT UNISORT DOUBLESORT Allgemeiner Ansatz fur¨ eine Dreiwege-Analyse UNARYSORT 3 Quicksort fur¨ vorsortierte Dateien Vorsortierung Runsort Zusammenfassung 2 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Neuer Ansatz mit Zweiteilung I

Eigene experimentelle Ergebnisse deuten an, dass sich der Aufwand fur¨ eine Dreiteilung der Folge mit durchschnittlich 3N/2 bin¨aren Schlusselvergleichen¨ bei kleinen Wiederholungsfaktoren von Schlusseln¨ nicht auszahlt. Mit anderen Worten: “To divide less is to conquer more!”

Wie wir zeigen werden, gibt es aber eine andere, neue Strategie. Die Idee ist, beim Durchlauf auf eine un¨are Teilfolge zu hoffen. Stellt sich die Teilfolge tats¨achlich als un¨ar heraus, ist nichts weiter zu tun. Ansonsten beginne mit dem ersten Schlusselwert¨ 6= dem Pivotelement H mit einer Zweiteilung, wobei die bisher gesehene Folge zur linken Teilfolge wird und der Rest geteilt wird in Folgen ≤ H und > H.

3 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Neuer Ansatz mit Zweiteilung II

Die Analyse dieser Quicksort-Variante, die wir unten als Linksort zeigen, ist trickreich und folgt im Grundsatz der Berechnung von Sedgewick fur¨ die obere Schranke [Sed77]. Das Resultat fur¨ die neue Strategie ergibt c¯ ≤ 2(N + 1)HN − 7N/3 − 1/3 fur¨ xi = 1 (alle Schlussel¨ verschieden) und 2NHn−1 + N fur¨ xi = M (1 ≤ i ≤ n), d.h. fur¨ den Fall mit konstantem Wiederholungsfaktor M = N/n. Zum Vergleich: fur¨ Trisort hatten wir 3(N + 1)HN − 4N und 3(N + M)Hn − 4N.

4 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Linksort

Der Einfachheit halber starten wir mit einer stabilen Version fur¨ verkettete Listen. Andere (nicht stabile) L¨osungen fur¨ Arrays sind aber genauso m¨oglich. Die notwendigen Anderungen¨ fur¨ die neue Strategie sind minimal (vgl. Listing 1).

Die Grundidee sieht man gut in der Abbildung 1. Klarerweise ben¨otigen wir einen weiteren Schlusselvergleich,¨ wenn wir den ersten Schlussel¨ 6= H entdecken. Danach testen wir immer auf ≤ H. Somit ist der Aufwand an Schlusselvergleichen¨ in der Teilephase fur¨ Folgen der L¨ange N genau N bei einer un¨aren Datei und N + 1 sonst.

5 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Linksort bildlich

first last

======? ?? = H ∧ not last 6= H = H ∧ last done! L1 ======test on < H

L2 ∅

Abbildung 1: Linksort mit Anfangssequenz gleich dem Pivotelement [Weg83].

6 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien

Listing 1: Linksort – un¨are Folgen erkennen. procedure LINKSORT( var first, last : r e f ) ; { linked list from first to last } {2 global dummy nodes sl and sr } l a b e l 9 9 ; var sf 1, sf 2, lt, rt : r e f ; H : keytype ; begin i f first = last then goto 9 9 ; { exit for singleton } lt := sl; lt ↑ .next := first ; { initialize empty sublist L1 } H := last ↑ .key { P i v o t = l a s t } ; while lt ↑ .next ↑ .key = H do begin { try for a unary file } i f lt ↑ .next = last then goto 9 9 ; { yes unary } lt := lt ↑ .next

7 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien

end ; { list contains a key 6= H } {do ordinary two−way s p l i t } rt := sr ; { initialize empty sublist L2 } i f lt ↑ .next ↑ .key > H then begin rt ↑ .next := lt ↑ .next ; repeat rt := rt ↑ .next u n t i l rt ↑ .next ↑ .key ≤ H ; lt ↑ .next := rt ↑ .next end ; { precondition for main partition loop: } {lt ↑ .next ↑ .key ≤ H } while lt ↑ .next <> last do begin

8 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien

repeat { r e p l a c e s lt := lt ↑ .next} lt := lt ↑ .next u n t i l lt ↑ .next ↑ .key ≥ H ; i f lt ↑ .next ↑ .key > H then begin rt ↑ .next := lt ↑ .next ; repeat rt := rt ↑ .next u n t i l rt ↑ .next ↑ .key ≤ H ; lt ↑ .next := rt ↑ .next end { then } end { w h i l e } ; { list partitioned } { sort subfiles recursively and reconnect } sf 2 := sr ↑ .next ; { s t a r t o f L2 saved } i f lt <> sl then LINKSORT(sl ↑ .next, lt ); { sort left sublist L1 } lt ↑ .next := last ;

9 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien

sf 1 := sl ↑ .next ; { s t a r t o f L1 saved ; i f L1 empty . . . } { ... then sf1 points to pivot node } i f rt <> sr then begin { s u b l i s t L2 not empty} LINKSORT(sf 2, rt ); last ↑ .next := sf 2 ; { connect pivot node to L2 } rt ↑ .next := n i l ; last := rt end { o f s o r t i n g L2 } first := sf 1 { return start of sorted list } 9 9 : end {LINKSORT} ;

10 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Kein Sch¨onheitspreis

Unglucklicherw¨ eise ist Linksort mit zwei goto-Anweisungen und den aufgerollten repeat- und while-Schleifen nicht sonderlich hubsch.¨ Als Ausrede verweisen wir darauf, dass wir eine optimierte Version zeigen, bei der wir einige Pointer- bzw. Indexvergleiche sparen k¨onnen. Man beachte auch, dass wir den letzten Schlussel¨ als Pivot w¨ahlen und damit bei einem Schlusselwert¨ > H nie hinten aus der Liste fallen k¨onnen.

11 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Die Analyse von Linksort I

Wir steigen jetzt ein in die Analyse von Linksort fur¨ Multimengen. Wie bereits erw¨ahnt, beginnt Linksort die Teilephase mit der Prufung¨ auf eine un¨are Folge. Hat die Folge die Form F = H, H,..., H sind wir fertig, sonst schalten wir um auf eine gew¨ohnliche Zweiwegeteilung und k¨onnen nur einen Schlussel¨ (H) aus der Rekursion herausnehmen. Der Ubergang¨ von Prufungen¨ auf =, 6= zu ≤, > ben¨otigt einen zus¨atzlichen Schlusselvergleich.¨

12 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Die Analyse von Linksort II

Fur¨ das Verhalten auf einer Multimenge {x1 · 1, x2 · 2,..., xn · n} mit n unterschiedlichen Werten k¨onnen wir auf zwei fundamentale Arbeiten von Sedgewick [Sed77] und Burge [Bur76] zuruckgreifen.¨

Theorem (Sedgewick) Sortiert ein Quicksort-Programm eine zuf¨allige bin¨are Datei mit durchschnittlich weniger als 2N · HN Vergleichen, dann braucht es nicht mehr als

2N(1 − 1/n)Hn−1 − 4N + ...

Vergleiche fur¨ eine zuf¨allige n-wertige Datei mit N Elementen.

13 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Linksort fur¨ bin¨are Eingabefolgen I

Linksort ist ein Quicksort-Program gem¨aß der Definition in der vorherigen Vorlesung und das Verhalten auf bin¨aren Dateien kann leicht analysiert werden. Lemma Um eine zuf¨allige bin¨are Datei mit N Elementen zu sortieren, ben¨otigt Linksort im Mittel genau

2N − 1 N(N − 3) 3N − − 2N−1 − 1 2N − 2 Vergleiche.

14 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Linksort fur¨ bin¨are Eingabefolgen II

Beweis. Wir mussen¨

x1 c¯(x1, x2) = x1 + x2 + 1 + [c¯(x1 − 1) +c ¯(x2)] + x1 + x2 x2 c¯(x1, x2 − 1) (1) x1 + x2

l¨osen und den Durchschnitt uber¨ alle Multinomialkoeffizienten x1 und x2 bilden. ! 1 N−1 N c¯ = X c¯(x, N − x) N 2N − 2 x x=1

15 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Linksort fur¨ bin¨are Eingabefolgen III

Theorem (Sedgewick) Ein Quicksort-Program, das N Elemente mit N + 1 Vergleichen teilt, ben¨otigt – im Mittel – nicht mehr als x x 2 X k j + 1 + x + . .. + x 4≤k+3≤j≤n k+1 j−1 n−2 n−3 X X c¯(xk , xk+1, xk+2) − c¯(xk+1, xk+2) (2) k=1 k=1

Vergleiche, um die Multimenge {x1, x2,..., xn} zu sortieren.

16 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Von der oberen Schranke zu Linksort

Diese obere Schranke fur¨ Quicksort-Programme taucht mit kleinen Anderungen¨ in der Analyse von Linksort wieder auf. In der Rekursionsgleichung unten haben wir N + 1 Vergleiche fur¨ die Teilephase um das Pivotelement H = j, und wir ziehen 1 von xj in der Rekursion ab, weil wir das Pivotelement nicht weiter sortieren (1 ≤ j ≤ n).

c¯(x1,..., xn) = N + 1 + 1 n X x (c¯(x ,..., x − 1) +c ¯(x ,..., x )) N j 1 j j+1 n j=1 fur¨ n > 1, c¯(x) = x, (3) woraus sich

17 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien

x x = 2 X k j + 1 + x + . .. + x 3≤k+2≤j≤n k j−1 n−1 x (x − 1) X 2 (x + x ) + k+1 k+1 + k k+1 x + 2 k=1 k xk xk+1 xk  − ! + xk + 1 xk + xk+1 xk   n−2 2   X xk+1  1   − 1 − x + x  !  k=1 k k+1  xk + xk+1 + xk+2  xk+2 n−2 X xk+1 (4) k=1 ergibt. 18 / 63 (5) Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Machen wir uns ein Bild ... I

Das ist eine sehr sperrige Formel. Um ein Gefuhl¨ fur¨ die relativen Vorzuge¨ einer Zweiwege- versus einer Dreiwegeteilung zu bekommen, ist es nutzlich,¨ mit festen Multiplikatoren zu argumentieren, d. h. einem Wiederholungsfaktor M, so dass N = M · n. Wie oben auf Folie 3 erw¨ahnt, braucht Linksort weniger als 2NHn−1 + N Pascal-Vergleiche, Trisort 3(N + M)Hn − 4N und die untere Schranke mit dreiwertigen MIX-Vergleichen lautet 2(N + M)Hn − 3N − n.

19 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Machen wir uns ein Bild ... II

Die Graphen dieser Funktionen fur¨ c¯M und eine Datei der Gr¨oße N = 1000 wird in Abbildung 2 gezeigt. Man beachte, dass die x-Achse eine logarithmische Skalierung hat.1 M wird gesetzt auf 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000 und l¨auft damit von paarweise verschiedenen Schlusseln¨ bis zur un¨aren Datei, die dann fur¨ Linksort und die untere Schranke N Vergleiche ben¨otigt, fur¨ Trisort aber 2N Vergleiche.

1Im Skript zur Vorlesung steht f¨alschlicherweise y-Achse. 20 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien

·104 2 TRISORT LINKSORT obere Schranke 1.5 LINKSORT gemessen untere Schranke

M 1 ¯ c

0.5

0 100 101 102 103 M Abbildung 2: Schlusselvergleiche¨ im Mittel

21 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Schw¨achen in der Absch¨atzung

Es stellt sich heraus, dass die obere Schranke 2NHn−1 + N fur¨ Linksort nicht scharf ist fur¨ kleine Werte von M. Daher zeigen wir auch experimentelle Messungen der Schlusselvergleiche¨ fur¨ 20 Permutationen. Diese Kurve ist andererseits ungew¨ohnlich uneben, vielleicht durch Einflusse¨ bei der Datengenerierung. Die Wiederholung dieser Experimente durch unabh¨angige Forscher – oder im Rahmen einer Sortiervorlesung – w¨are begrußenswert.¨

22 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Schlussfolgerung

Die wesentliche Einsicht ist, dass eine billige Teilungsstrategie, die versucht, un¨are Teilfolgen am Ende zu fangen, nicht sehr viel langsamer ist als eine teure Strategie, die Duplikate fruh¨ entdeckt, sofern nur recht viele Duplikate auftauchen. Dafur¨ ist sie deutlich schneller, wenn keine oder nur wenige Duplikate vorhanden sind.

Besonders der Fall M = 2 tritt in der Praxis h¨aufig auf,2 wenn zwei beinahe gleiche Listen zur Entdeckung fehlender Duplikate zusammengeschmissen und dann sortiert werden, statt sie einzeln zu sortieren und dann zu mischen und zu prufen.¨

2Etwa in einer Liste von Online-Reservierungen, die alle noch einer Best¨atigung bedurfen,¨ die in einer zweiten Liste festgehalten wird. 23 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Med-3-Quicksort versus Linksort versus Trisort

Wir veranschaulichen das Argument nochmal mit einer Grafik fur¨ die Ausfuhrungszeiten¨ (vgl. Abbildung 3), die zu Zeiten der Turku-Vorlesung mit den gleichen Einstellungen (N = 1000, 20 Permutationen, unterschiedliche Wiederholungsfaktoren M) wie oben gemessen wurden.

Hinzugenommen wurden die Ausfuhrungszeiten¨ fur¨ Sedgewicks hochoptimierten Median-von-drei-Quicksort mit Eliminierung kurzer Teilfolgen. Eine Tabelle aller Messungen, einschließlich einiger Array-Varianten, findet sich auf Folie 58 unten.

24 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien

1

0.8 TRISORT LINKSORT 0.6 Med-3-Quicksort

Sekunden 0.4

0.2

0 100 101 102 103 M Abbildung 3: Ausfuhrungszeiten¨ im Mittel fur¨ N = 1000

25 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Letzte Worte zu Trisort und Linksort

Der zweite Graph verdeutlicht nochmals unser Argument: sp¨ate Duplikatsentdeckung in Linksort ist geringfugig¨ langsamer fur¨ hohe Werte von M, funktioniert aber gut fur¨ die wichtigen F¨alle M = 1 und M = 2. Median-von-drei-Quicksort zieht keinen Nutzen aus Multimengen, degeneriert aber auch nicht, wie es einem Quicksort passieren wurde,¨ wenn dieser sich fur¨ die Pivotwahl nur auf einen Schlussel¨ stutzt.¨

26 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Funf¨ Wege zur Beschleunigung auf Arrays

Wir haben jetzt zwei Methoden gesehen, wie man Quicksort beschleunigen kann fur¨ Eingaben mit Duplikaten, im Fall Linksort auch ohne sich wesentliche Nachteile einzuhandeln, falls doch alle Schlussel¨ paarweise verschieden sind. Diese Ideen fur¨ fruhe¨ oder sp¨ate Duplikatsentdeckung wurden auf Versionen fur¨ verkettete Listen angewandt, was den Zusatznutzen der Stabilit¨at (S¨atze mit gleichen Schlusseln¨ behalten ihre relative Eingabeordnung) einbringt.

Die Frage ist nun, ob sich diese Ideen der Zweiwege- und Dreiwegeteilung auch auf Arrays ubertragen¨ lassen? Die Antwort ist ja, wie Wegner in [Weg85] mit funf¨ L¨osungen, die alle in situ, aber nicht stabil sind, zeigt.

27 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Slidesort

Die erste Idee besteht darin, die Datei von beiden Seiten mit dem Ziel einer Dreiwegeteilung (fruhe¨ Duplikatsentdeckung) durchzuk¨ammen. S¨atze mit einem Schlussel¨ gleich dem Pivot bilden eine mittlere Teilfolge, die nach rechts “rutscht”. Eine effiziente Methode dafur¨ ist das “Rad”, eine Datenstruktur, die wir schon im Zusammenhang mit Lomutos Quicksort besprochen haben.

Wie dort ausgefuhrt,¨ zerst¨ort das Anfugen¨ von S¨atzen im Wechsel mit Drehungen des Rads die Ordnung gleicher Schlussel.¨ Andererseits sind auch die anderen Vertauschungen in der Teilephase Schuld an mangelnder Stabilit¨at, wie man in Abb. 4 sieht.

28 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien

scan scan

< = < ? > x i j

< = > ? < > x i j

< = > ? = > x i j

Abbildung 4: SLIDESORT – Dreiwegeaufteilung mit verschieblicher

Pivotfolge 29 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Grundidee Slidesort

Im Kern bestimmt der gerade inspizierte Schlussel¨ an der Position i, was passiert. Ist er kleiner als das Pivotelement H, wird das “Rad” mit den Schlusseln¨ = H gerollt. Ist A[i] = H, wird das Rad gestreckt (nicht in Abbildung 4 gezeigt). Wenn A[i] > H, suchen wir von rechts bis wir in Position A[j] einen Schlussel¨ ≤ H finden, den wir mit A[i] tauschen. Falls in diesem Fall A[j] echt kleiner ist als H, machen wir einen Dreieckstausch, wie in der Mitte von Abbildung 4 gezeigt, sonst nur einen gew¨ohnlichen swap von A[i] mit A[j].

30 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Head&Tail-Sort

Hat man mal die “Rad-Technik” verstanden, lassen sich andere Strategien leicht verwirklichen. Eine Strategie ist wieder eine Dreiwegeteilung mit fruher¨ Duplikatsentdeckung, aber mit zwei Pivot-Teilfolgen links und rechts. Entsprechend nennen wir diese Quicksort-Variante Head&Tail-Sort. Die Pivotfolgen werden am Ende der Teilung in die Mitte getauscht. Die Details kann man der Abbildung 5 entnehmen.

31 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien

scan scan = < > ? < > = x i j y

= < > ? = > = x i j y

= < = ? < > = x i j y

= < = ? = > = x i j y

Abbildung 5: HEAD&TAIL-SORT – Dreiwegeteilung mit zwei Pivotfolgen

32 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Nicht stabil und obendrein langsam

Wieder l¨asst sich Stabilit¨at nicht herstellen. Neben dieser Eigenschaft, die alle hier vorgestellten Array-Varianten mit Beschleunigung fur¨ Multimengen betrifft, verlangsamt das Tauschen der Pivotschlussel¨ in die Mitte am Ende der Teilungsphase das Verfahren, wenn viele Duplikate auftreten. Die Laufzeiten findet man in der Tabelle auf Folie 58.

33 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Unisort

Unisort ist ein unidirektionaler Quicksort mit Dreiwegeteilung (fruhe¨ Erkennung von Duplikaten). Nur eine Teilfolge fur¨ Pivotelemente wird am linken Rand gebildet.

scan

= < = ? > x i j

= < > ? ? > x i j

Abbildung 6: UNISORT – Dreiwegeteilung mit einer Pivotfolge links

34 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Ahnlichk¨ eiten zu Lomutos Quicksort

Unisort ¨ahnelt Head&Tail-Sort, indem es eine Teilfolge von Pivotelementen bildet, die nachher in die Mitte getauscht werden mussen.¨ Ahnlichkeiten¨ gibt es auch zu Lomutos Verfahren, das ebenfalls unidirektional ist. Wieder ist damit die Anzahl der Vertauschungen h¨oher. Wie man in Abbildung 6 sieht, wird ein Satz ri mit Schlusselwert¨ > H getauscht mit rj unabh¨angig vom Wert in rj . Naturlich¨ k¨onnte man das auch mit einem zweiten Scan von rechts ¨andern. Im Großen und Ganzen ist diese Variante aber nicht konkurrenzf¨ahig, dafur¨ ist der Programmcode diesmal erfreulich kurz.

35 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Doublesort – h¨alt doppelt besser?

Die fruhe¨ Entdeckung von Duplikaten in einer Dreiwegeteilung mit bin¨aren Pascal-Vergleichen verlangt einen zweiten Vergleich fur¨ Schlussel¨ ≤ H bzw. ≥ H. Bisher haben wir diesen Test sofort durchgefuhrt,¨ man k¨onnte ihn aber auch zuruckstellen¨ fur¨ einen zweiten Durchgang. Genau das macht Doublesort.

36 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Doublesort

first scan

< ≥ ? < ≥ i j

second scan

< = > ? = > i x y

Abbildung 7: DOUBLESORT – Dreiwegeteilung in zwei Durchl¨aufen

37 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Vor- und Nachteile und der Teufel im Detail

Doublesort hat den Vorteil, dass wir am Ende der Teilungsphase keine S¨atze in die Mitte schaufeln mussen.¨ Das erledigt jetzt der zweite Durchlauf. Andererseits hat man zus¨atzliche Indexvergleiche, die die Schleifen kontrollieren. Alle Versionen, einschließlich der beiden noch ausstehenden, enthalten trickreiche Details fur¨ Sonderf¨alle, etwa wenn leere Teilfolgen entstehen (wenn H der gr¨oßte oder kleinste Schlussel¨ ist) oder wenn eine leere Eingabe, bzw. eine Datei mit nur einem Satz, gegeben ist.

38 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Allgemeiner Ansatz fur¨ eine Dreiwege-Analyse I

Ehe wir uns die Array-Variante von Linksort, also eine Zweiwegeteilung mit sp¨ater Duplikatsentdeckung, ansehen, wollen wir am Beispiel von Slidesort andeuten, wie man eine Dreiwegeteilung analysiert. Wir fangen mit der Z¨ahlung der extra Schlusselvergleiche¨ an, die Slidesort zus¨atzlich zu den N Vergleichen pro Teilungsphase braucht. Nehmen wir an, der erste Vergleich fur¨ jeden Schlussel¨ bei den Durchl¨aufen von links und rechts erfolge so, wie in Abbildung 8 dargestellt.

39 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Allgemeiner Ansatz fur¨ eine Dreiwege-Analyse II

first test on = first test on >

1 0 2 2 0 1 2 2 0 2 0 1

0 0 0 0 1 1 1 2 2 2 2 2

| {z }| {z }| {z } F1 FH F2

Abbildung 8: SLIDESORT Beispiel mit H = 1

40 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Wann tritt ein zweiter Vergleich auf?

Die erste – eher triviale – Beobachtung ist, dass die Anzahl der Schlussel¨ > H in F1 und in FH gleich ist der Anzahl von Schlusseln¨ ≤ H in F2. Somit ist die Anzahl der extra Schlusselvergleiche¨ in der Teilungsphase

= #Schlussel¨ 6= H im linken Scan (F1 und FH ) +

#Schlussel¨ ≤ H im rechten Scan (F2)

= 2 · #Schlussel¨ > H im linken Scan (F1 und FH ) +

# Schlussel¨ < H im linken Scan (F1 und FH ).

41 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien

Abbildung 9 zeigt die Situation nochmals, jetzt mit Multinomialkoeffizienten.

∀kj 6= H ∀kj ≤ H

< H = H > H

| {z }| {z }| {z } x1+...+xi−1 xi xi+1+...+xn

Abbildung 9: SLIDESORT Zusatzvergleiche

42 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien

Die Gesamtzahl der Schlusselvergleiche¨ ist dann 1 N + X x (x + . .. + x ) + N i 1 i−1 1≤i≤n 1 X X x · t · p(t) N i 1≤i≤n 0≤t≤xi+1+...+xn

mit ! ! x1 + ... + xi xi+1 + ... + xn t xi+1 + ... + xn − t p(t) = ! N xi+1 + . .. + xn wobei t die Anzahl der Schlussel¨ ≤ H ist, die im Durchlauf von rechts entdeckt werden. p(t) bildet man aus der Anzahl an Kombinationen ohne Wiederholung.

43 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien

Eine Umformulierung mit zweimaliger Anwendung von Vandermondes Identit¨at und die Beobachtungen von oben bringen uns zur durchschnittlichen Anzahl von Schlusselvergleichen¨ in der Teilungsphase: 1 N + X x ( X s · p (s) + X 2t · p (t)) N i i i 1≤i≤n 0≤s≤x1+...+xi−1 0≤t≤xi+1+...+xn

mit xi+1 + ... + xn = |F2|, ! ! , ! x1 + ... + xi xi+1 + ... + xn N pi (s) = s x1 + ... + xi − s x1 + ... + xi

und pi (t) entsprechend. Die Tabelle auf Folie 49 unten zeigt Vergleiche und Tauschoperationen fur¨ jede der Varianten im Spezialfall N = n (alle Schlussel¨ paarweise verschieden).

44 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Unarysort

Was bisher fehlt, ist eine Variante, die der Linksort-Linie folgt, d. h. eine Zweiwegeteilung macht mit sp¨ater Duplikatsentdeckung. Bekanntlich brauchte man dafur¨ einen extra Schlusselvergleich¨ je Teilungsphase. Die Array-Variante heißt Unarysort, weil sie auf eine un¨are Teilfolge “hofft”. Das Verfahren setzt einen Stopper-Schlussel¨ in A[N + 1] voraus, der gr¨oßer ist als A[1].key.

45 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien

Listing 2: Unarysort – entdeckt un¨are Folgen. procedure UNARYSORT(l, r : in teg er ); { sort recursively an array a[l..r] eliminating unary subfiles , but examining each key exactly once except for one key; assumes a[N + 1] > a[1] for the original file in a[1..N]} var i, j : in teg er ; H , aux : keytype { elements are keys only } ; begin {UNARYSORT} ; H := a[l]; i := l + 1; {a unary subfile?} while a[i] = H do i := i + 1 ; {a[i] 6= H } i f i ≤ r { not unary } then begin { p a r t i t i o n }

46 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien

i := i − 1; j := r + 1 ; while i < j do repeat i := i + 1 u n t i l a[i] > H ; repeat j := j − 1 u n t i l a[j] ≤ H ; swap (a[i], a[j]) end { w h i l e } { switch back a[i], a[l], a[j]} c i r c (a[i], a[l], a[j] ); {a circular swap, i.e. circ(a,b,c): temp := a; a := b; b:= c; c := temp} i f l ≤ j − 1 then UNARYSORT(l, j − 1) ; i f i < r then UNARYSORT(i, r) end { then } end {UNARYSORT} ;

47 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Bewertung Unarysort

Das Programm fur¨ Unarysort ¨ahnelt sehr dem klassischen Quicksort, bei dem ein Satz aus der Rekursion eliminiert wird. In der Tat haben wir eigentlich nur einen kleinen Vorspann eingebaut, der das Vorliegen einer un¨aren Folge pruft.¨

Wie oben gezeigt, ist das genauso effektiv wie fruhe¨ Duplikatsentdeckung, aber deutlich billiger was zus¨atzliche Schlusselvergleiche¨ anbetrifft. Das zeigt auch die folgende Tabelle 1 mit Laufzeiten in der rechten Spalte fur¨ den Fall N = n = 1000. Gemessene Laufzeiten fur¨ andere F¨alle finden sich in Tabelle 2 am Ende dieser Lektion auf Folie 58.

48 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien

Tabelle 1: Aufwand in der Teilephase (Zeiten in Sekunden)

Spezialfall N = n MIX Vergl. Pascal Vergl. Vertauschungen Zeit TRISORT N 9N/6 – 1.03 HEAD & TAIL N ≤ 8N/6 N/6 + . .. 1.38 UNI N 9N/6 N/2 + . .. 2.25 SLIDE N 10N/6 N/2 1.96 DOUBLE 3N/2 9N/6 N/6 1.44 LINKSORT N N + 1 – 0.90 QUICKSORT N N N/6 1.08 UNARYSORT N N + 1 N/6 1.23

49 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Vorsortierung I

Bisher bezog sich Smoothness (eine Beschleunigung) auf das Verhalten von Quicksort fur¨ Multimengen. Oft erwartet man eine ¨ahnliche Beschleunigung, wenn die Eingabe bereits ganz oder in Teilen vorsortiert ist. Hier ist es jedoch so, dass keines der vorgestellten Sortierverfahren dies leistet. Noch schlimmer ist, dass es ohne weitere Vorsichtsmaßnahmen – etwa eine Median-von-drei-Pivotwahl – sogar zu einer quadratischen Entartung der Laufzeit kommt.

50 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Vorsortierung II

Der Begriff Vorsortierung wurde bereits fruher¨ erw¨ahnt. Der Algorithmus von C. R. Cook und Do Jiu Kim fur¨ nahezu sortierte Listen [CK80] sowie der von Edsger W. Dijkstra publizierte Smoothsort [Dij82] profitieren beide von nicht-zuf¨alligen Eingaben. Vorsortierung kann man formal definieren, wie es etwa Heikki Mannila [Man85] macht, der die Anzahl R der S¨atze z¨ahlt, die man entfernen musste,¨ damit die verbleibenden eine aufsteigende Folge bilden. Diese Zahl setzt man dann in Beziehung zur Eingabel¨ange N. Oft taucht in der englischen Literatur der Begriff “run” (oder “upward run”) in Zusammenhang mit “presortedness” auf, was im Deutschen ein Lauf w¨are. Gemeint sind Folgen aufsteigender Schlusselwerte¨ innerhalb einer Permutation. Die H¨aufigkeit und L¨ange solcher L¨aufe kann man auch als Maß der Vorsortierung nehmen. Knuth definiert das pr¨azise in [Knu98, p. 35ff.].

51 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Runsort

Wir schlagen hier eine Quicksort-Variante Runsort vor, die – ¨ahnlich zu Linksort und Unarysort – auf einen Lauf “hofft” und, wenn sie einen findet, die Rekursion fur¨ diese schon sortierte Folge abbricht. Findet der Durchlauf der Teilfolge keine vollst¨andige Sortierung, wird ab der Entdeckungsstelle wie gewohnt geteilt. Abbildung 10 veranschaulicht die generelle Strategie.

52 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien

≤? ≤?

a1 ≤ a2 ≤ . .. ≤ ai ? aj ≤ . .. ≤ an−1 ≤ an

i j ≤?

run broken & i < j − 1 ⇒ split a[i + 1 : j − 1] i ≥ j − 1 ⇒ done

Abbildung 10: RUNSORT – Suche nach einem Lauf

53 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien

Listing 3: Runsort – Vorsortierung entdecken. procedure RUNSORT (l, r : in teg er ); var i, j : in teg er ; H : keytype ; procedure swap ( var a , b : keytype ) ; ... begin {RUNSORT} ; i f a[l] > a[r] then swap (a[l], a[r]) ; i := l; j := r ; while (i + 1 < j) and (a[i] ≤ a[i + 1]) and (a[j − 1] ≤ a[j]) and (a[i + 1] ≤ a[j − 1]) do begin i := i + 1; j := j − 1 end ; i f i < j − 1 { not a run } then begin { p a r t i t i o n }

54 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien

H := (a[i] + a[j]) div 2 ; repeat repeat i := i + 1 u n t i l a[i] ≥ H ; repeat j := j − 1 u n t i l a[j] ≤ H ; i f i < j then swap (a[i], a[j]) u n t i l i ≥ j ; i f l < i − 1 then RUNSORT(l, i − 1) ; i f j + 1 < r then RUNSORT(j + 1, r) ; end {i < j − 1} end {RUNSORT} ;

55 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Details der Pivotwahl von Runsort

Ein schwieriger Aspekt von Runsort ist die Pivotwahl, wenn die Suche nach einem kompletten Lauf fehlschl¨agt. Wie der Code in Listing 3 zeigt, weichen wir auf ein fiktives Pivotelement aus, das wir aus (a[i] + a[j]) div 2 berechnen. Damit sind wir auf der sicheren Seite, weil a[i] das Maximum der bisher gesehenen linken Teilfolge ist und a[j] das Minimum der rechten Teilfolge ist. Ferner ist a[i] ≤ a[j].

56 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Qualit¨atsbetrachtungen zu Runsort

Im großen Ganzen kann Runsort mit dem Sortierverfahren von Cook und Kim [CK80] mithalten und schl¨agt Dijkstras Smoothsort locker. Andererseits kann ein Teile&Tausche-Sortierverfahren nicht wirklich mit L¨aufen in der Eingabe umgehen, es sei denn, es w¨aren “L¨aufe von L¨aufen”. In Tabelle 2 haben wir auch eine Eingabe aufgenommen, die aus zwei benachbarten L¨aufen von einmal 900 und dann 100 Schlusseln¨ in einer Datei der L¨ange N = 1000 besteht (S¨agezahnfolge). Die Ausfuhrungszeit¨ zeigt, dass Runsort davon nicht profitiert, aber immerhin tritt keine Degenerierung auf.

57 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien

Tabelle 2: Ausfuhrungszeiten¨ fur¨ einige Verfahren und Datenarten

N = 1000 keys multisets presorted files (in percent) 2 runs algorithm random M = 2 M = 10 M =100 M=500 M=1000 p=0 p=5 p=10 p=20 p=50 900/100 Quicksort 1.08 1.01 1.00 1.03 1.08 1.05 – –––– – (textbook) Quicksort 0.99 0.95 0.90 0.89 0.95 1.02 0.50 0.51 0.54 0.62 0.82 0.91 (Sedgewick) Trisort 1.03 0.86 0.57 0.26 0.12 0.10 – –––– – Linksort 0.90 0.85 0.66 0.38 0.18 0.06 – –––– – Head&Tail 1.38 1.21 0.87 0.51 0.31 0.26 – –––– – Unisort 2.25 2.05 1.50 0.69 0.38 0.25 – –––– – Slidesort 1.96 1.68 1.39 0.45 0.15 0.05 – –––– – Doublesort 1.44 1.28 0.85 0.40 0.17 0.10 – –––– – Unarysort 1.23 1.14 0.82 0.42 0.18 0.05 – –––– – Heapsort 2.41 2.40 2.40 2.25 1.43 0.64 2.52 2.50 2.50 2.48 2.45 2.52 (textbook) Smoothsort 6.75 6.75 6.64 5.62 2.80 0.91 0.96 1.42 1.80 2.62 4.65 5.43 (Dijkstra) Cook-and- 1.41 1.39 1.31 1.32 1.16 0.64 0.26 0.44 0.58 0.79 1.21 0.54 Kim-Sort Runsort 1.31 1.25 1.09 0.74 0.42 0.12 0.11 0.54 0.66 0.79 0.94 1.31

58 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Zusammenfassung I

Das Anliegen dieser Folien war, zu zeigen, dass Sedgewick [Sed77, p. 244] zu pessimistisch war, als er vermutete, dass kein Verfahren in die N¨ahe der unteren Schranke fur¨ Quicksort auf Multimengen komme. Sowohl eine Dreiwegeaufteilung mit fruher¨ Erkennung von Duplikaten ist m¨oglich, als auch eine Zweiwegeaufteilung mit sp¨ater Erkennung un¨arer Teilfolgen. Die beiden Versionen Trisort und Linksort fur¨ verkettete Listen sind dabei besonders schnell und naturlich¨ stabil.

59 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Zusammenfassung II

Bei den Array-Versionen w¨are besonders Unarysort ein guter Kandidat fur¨ weitere Verbesserungen mittels Median-von-drei-Pivotwahl und Wechsel zur Sortierung per Einfugen¨ fur¨ kurze Teilfolgen. Der zus¨atzliche Schlusselvergleich¨ pro Teilfolge ist eine gute Investition und funktioniert fur¨ Multimengen mit signifikanter Anzahl an Duplikaten so gut wie eine Dreiwegeaufteilung. Ist andererseits die Eingabe eine echte Menge, ergeben sich insgesamt h¨ochstens 2N “unn¨otige” Schlusselvergleiche¨ (siehe die Formel (12.3) im Anhang des Skripts). Diese 2N ließen sich nochmals erheblich verringern, wenn man kurze Teilfolgen gesondert behandelt.

60 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Zusammenfassung III

Eine zuverl¨assige Pivotwahl, z. B. Median-von-drei (geht nicht fur¨ verkettete Listen) wurde¨ auch die unscheinbaren kleinen Striche in der Tabelle von Folie 58 beseitigen. Jeder steht fur¨ die peinliche Tatsache, dass das Verfahren deutlich degeneriert, sofern eine Vorsortierung vorliegt, was in der Praxis nicht selten auftritt. Die gute Nachricht lautet aber, dass wir immer noch doppelt so schnell sind wie der einzige andere Mitbewerber fur¨ in situ Sortieren mit einer Laufzeit O(N log N) im Mittel und schlechtesten Fall – Heapsort.

61 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Literatur I

[Bur76] William H. Burge, An analysis of binary search trees formed from sequences of nondistinct keys, J. ACM 23 (1976), no. 3, 451–454. [CK80] C.R. Cook and D.J. Kim, Best sorting algorithms for nearly sorted lists, Communications of the ACM 23:11 23 (1980), 620–624. [Dij82] Edsger W. Dijkstra, Smoothsort, an alternative for sorting in situ, Sci. Comput. Program. 1 (1982), no. 3, 223–233. [Knu98] Donald E. Knuth, The Art of Computer Programming. Vol. 3: Sorting and Searching, 2nd ed., vol. 3, Addison-Wesley, 1998. [Man85] H. Mannila, Measures of presortedness and optimal sorting algorithms, IEEE TC C-34 (1985), 318–325.

62 / 63 Quicksort fur¨ Multimengen in verketteten Listen Quicksort fur¨ Multimengen auf Arrays Quicksort fur¨ vorsortierte Dateien Literatur II

[Sed77] R. Sedgewick, Quicksort with equal keys, SIAM J Comput 6, No. 2 (1977), 240–267. [Weg83] Lutz Wegner, The linksort family-design and analysis of fast, stable quicksort derivatives, Tech. Report Report 123, Institut fur¨ Angewandte Informatik und Formale Beschreibungsverfahren, Universit¨at Karlsruhe, 1983. [Weg85] , Quicksort for equal keys, IEEE TC C-34 No. 4 (1985), 362–367.

63 / 63 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren

Sortierverfahren Ein externer Quicksort

Lutz Wegner

5. Juni 2014

1 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Inhaltsverzeichnis

1 Besonderheiten externer Sortierverfahren Was die Literatur sagt

2 EXQUISIT - Ein externer Quicksort Experimente in den Achtzigern Analyse von EXQUISIT Ergebnisse der Experimente

3 Andere externe Sortierverfahren Mergesort als Mitbewerber Verkamos Beobachtung Der Monard-Algorithmus

2 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Lokalit¨at der Referenzen – Mythos oder Wahrheit?

Eine naturliche¨ Frage lautet: “Ist Quicksort ein guter Kandidat fur¨ externes Sortieren?” Die folgenden Antworten sprechen gegen Quicksort. What sorting algorithm should be used? The method of merging is a fairly natural choice; other methods of internal sorting do not lend themselves so well to a disk implementation, . . . [Knu98, p. 264]

The severity of interpass paging depends on the size of real storage, because the locality shifts dramatically after a pass. [Lor75, p. 342]

3 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren FIFO-Quicksort versus FIFO-Mergesort

Brawn, Gustavson und Mankin [BGM70] berichten, dass ein FIFO-Quicksort schlechter ist als FIFO-Sortieren-durch-Mischen (merging). Andere beachtenswerte Kommentare zum externen Sortieren – besonders im virtuellen Speicher – findet man in [TAH84], [CK80], [Den68], [Den80], [Pet74], [Sed78], [Sha85], [Ver86], [Wai85] und [Wal77].

4 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren EXQUISIT - Ein externer Quicksort

Trotz dieser schlechten Vorhersagen entschieden sich Hans-Werner Six und Lutz Wegner, Quicksorts Verhalten als externes Sortierverfahren n¨aher zu untersuchen [SW84], woraus ein Verfahren namens Exquisit entstand. Unter der Annahme, dass das Verfahren die Daten blockweise liest und schreibt, schauen wir uns eine Datei F mit 4 Bl¨ocken an, die in einen (FIFO-)Puffer S geladen werden, der gleichzeitig zwei Bl¨ocke halten kann. Nehmen wir ferner an, dass wir einen “traditionellen” bidirektionalen Quicksort haben, d.h. es gibt Durchl¨aufe von links und von rechts, um die Datei zu teilen. Die Abbildung 1 zeigt den m¨oglichen Ablauf.

5 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren EXQUISIT bildlich

A B C D F

| {z } | {z } F F | {z } | 1 {z } 2 F11 F12 0 1 S A D B C ... A D ...

Abbildung 1: Lesen und Schreiben der Bl¨ocke in Exquisit

6 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren EXQUISIT Voruberlegungen¨

Die folgenden Punkte sollte man beachten, bevor man versucht, herauszufinden, wie gut (oder schlecht) die Idee insgesamt ist. Shackelton [Sha85] berichtet, dass ein externer Quicksort in England in den Sechzigern auf einem ATLAS-Rechner in Gebrauch war, der aber nie analysiert wurde. Ein fiktives Pivotelement H = (firstkey + lastkey)/2 oder ¨ahnlich (min + max)/2 w¨are von Vorteil. Bl¨ocke werden nach Bedarf geladen (fetch on-demand) und verz¨ogert zuruckgeschrieben¨ (delayed rewriting). Wir sortieren die linke Teilfolge zuerst und verwenden indirekte “Pufferadressierung”. Quicksort-Varianten mit einem fiktiven Pivotelement lassen sich leicht entwerfen (siehe Listing 1).

7 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Quicksort mit fiktivem Pivotelement I

Listing 1: QUICKS – Quicksort mit fiktivem Pivotelement. procedure QUICKS(l, r : in teg er ); var lt, rt, H, aux : in teg er ; begin lt := l − 1; rt := r + 1 ; H := (s[l] + s[r]) div 2 ; { pivot selection } while lt < rt do begin repeat lt := lt + 1 u n t i l s[lt] ≥ H ; repeat rt := rt − 1 u n t i l s[rt] ≤ H ; i f lt < rt then begin { pointers have not crossed } aux := s[lt]; s[lt] := s[rt]; s[rt] := aux ; end

8 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Quicksort mit fiktivem Pivotelement II

end ; i f l < lt − 1 then QUICKS (l, lt − 1) ; i f rt + 1 < r then QUICKS (rt + 1, r) end { o f QUICKS} ;

9 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Analyse von EXQUISIT

Exquisit ist trivialerweise ein Algorithmus mit O(N log N) Schlusselvergleichen¨ mit denselben Konstanten wie andere bidirektionale Quicksorts auch. Das wichtige Maß fur¨ uns ist aber die Anzahl der Blockzugriffe! Definition Bezeichne L(F ) die Position des ersten Satzes von F im ersten Block (in der ersten Seite) der Datei F , L(F ) ∈ {1,..., s}, s die Seitengr¨oße.

10 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren EXQUISIT Annahmen in der Analyse I

Um zu einer sinnvollen Analyse zu kommen, brauchen wir einige Annahmen bezuglich¨ zuf¨alliger Anordnungen. 1) Die Datei F ist eine zuf¨allige Permutation der S¨atze und die Schlussel¨ sind paarweise verschieden; ohne Beschr¨ankung der Allgemeinheit seien die Schlussel¨ in F die Menge der naturlichen¨ Zahlen, d.h. keys(F ) = {1, 2,..., N}. 2) L(F ) ist gleichm¨aßig verteilt uber¨ 1,..., s, 1 p(L(F ) = k) = s (F f¨angt auf einer zuf¨alligen Position im ersten Block an). 3) Alle N − 1 Pivotpositionen sind gleichwahrscheinlich, d.h. wenn F aufgeteilt wird in F1 und F2, dann ∃k, k ∈ {1,..., N − 1} mit 1 |F1| = k, |F2| = N − k, p(|F1| = k) = (N−1) (fiktives Pivotelement).

11 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren EXQUISIT Annahmen in der Analyse II

Lemma

Habe F eine Gr¨oße von k ≥ 5 Bl¨ocken. Wenn F schon in F1 und F2 aufgespalten wurde, jeweils mit > 2 Bl¨ocken, dann brauchen wir fur¨ jede Splitposition t ∈ 1,..., N − 1 nachfolgend k − 1 Blocklesevorg¨ange, um wiederum jeweils F1 und F2 aufzuspalten.

12 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Beweis Lemma

Der Beweis l¨asst sich aus der folgenden Abbildung 2 herleiten.

F1 F2 z }| { z }| {

1 . .. i i + 1 . .. k F

| {z } | {z } F1 F2

Abbildung 2: M¨ogliche Splitpositionen im externen Quicksort

Mit Ausnahme des allerersten Durchgangs ist der linkeste Block einer Datei immer schon im HS, es sei denn, die Teilung f¨allt genau auf eine Blockgrenze. Somit haben wir fur¨ F1 gerade i − 1 Lesevorg¨ange und fur¨ F2 k − i Lesevorg¨ange, zusammen k − 1.  13 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren EXQUISIT Analyse (Forts.) I

Man beachte, dass k − 1 eine obere Schranke ist fur¨ |Fi | < 3 Bl¨ocke. Definition Bezeichne K(L(F )) die Anzahl der Bl¨ocke, die F mit Startposition L(F ) belegt.

Die folgenden Resultate werden ohne weiteren Beweis aufgefuhrt,¨ weil sie direkt auf kombinatorischen Z¨ahlungen beruhen.

14 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren EXQUISIT Analyse (Forts.) II

Lemma Die obere Schranke fur¨ die Anzahl der Blocklesevorg¨ange – wenn F ursprunglich¨ schon gespalten ist – berechnet sich zu

1 s g(N) = X (K(L(F )) − 1) + s L(F)=1 N−1 1 X (g(t) − g(N − t)) fur¨ N > s + 1 N − 1 t=1

g(N) = 0 fur¨ N ≤ s + 1.

15 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren EXQUISIT Analyse (Forts.) III

Lemma Die durchschnittliche Anzahl von Bl¨ocken, die eine Datei der Gr¨oße N bei Blockgr¨oße s belegt, ist

1 s N − 1 X K(L(F )) = + 1. s s L(F)=1

Theorem Die erwartete Anzahl der Blocklesevorg¨ange (expected number of block reads EBR(N)) zum Sortieren einer Datei der Gr¨oße N ist

2N  N  3N N ≤ ln + + 1 − s s + 1 s s(s + 1)

16 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren EXQUISIT Zusammenfassung

N 0 Fazit: Fur¨ große N haben wir M = s Bl¨ocke fur¨ F . Sei EBR die Anzahl der Blocklesevorg¨ange als Funktion der Anzahl der Bl¨ocke M, dann ist EBR0(M) = 2M ln M + 3M.

Das trifft sich mit unserer tats¨achlichen Messung, die ≈ 1, 5M ln M liefert. Was aber passiert im schlimmsten Fall? Bedeutet eine durchschnittliche Anzahl von O(M log M) Blocklesevorg¨angen eine O(M2) Degeneration? Unglucklicherweise¨ nicht. Im schlimmsten Fall entfernt jede Teilphase nur einen der N S¨atze und verlangt das Laden aller K/s Bl¨ocke fur¨ eine Teilfolge der Gr¨oße K(1 ≤ K ≤ N). Asymptotisch ergibt dies O(N · M).

17 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren EXQUISIT Beispielrechnung

Beispiel Sei die Dateigr¨oße |F | = N = 50000 S¨atze mit s = 50 S¨atzen je Block. Jeder Satz habe einen Schlussel¨ mit 9 Ziffern. Dann ist M = 1000, 2M ln M + 3M ≈ 16815. Fur¨ eine Platte mit einer Lese-/Schreibzeit von 18 ms sortieren wir die Datei in 300 s = 5 min im Mittel, vorausgesetzt der E/A-Verkehr dominiert die Sortierzeit.

Im schlechtesten Fall haben wir NM = 50000 · 1000 = 50000000 (50 Millionen) Blocklese- und Schreibvorg¨ange, was zu einer Sortierzeit von ca. 250 Stunden oder mehr als 10 Tagen fuhrt!¨ Um das zu verhindern, ist eine (min + max)/2-Strategie fur¨ die Pivotwahl empfehlenswert, wodurch der schlechteste Fall zu O(M log max) wird. Bei Schlusseln¨ mit maximal 9 Ziffern h¨atten wir dann ≤ 30000 Blockzugriffe in ≤ 9 Minuten.

18 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Kopfbewegungen

Auf der Folie 11 diskutierten wir die Annahmen bezuglich¨ der Platzierung der Datei auf einer Platte. Die vermutlich einzig sichere Aussage fur¨ ein Zugriffskostenmodell lautet, dass benachbarte Bl¨ocke mit großer Wahrscheinlichkeit schnelleren Zugriff haben als weit auseinanderliegende. Das betrifft Bl¨ocke in einem Zylinder und – weniger deutlich – benachbarte Zylinder.

Um einen Ansatz fur¨ das Sortieren mit ungleich verteilten Blockzugriffszeiten zu bekommen, betrachten wir ein lineares Blockmodell und messen die Abst¨ande (als Anzahl der Bl¨ocke) zwischen aufeinanderfolgenden Lese- und Schreiboperationen1.

1Ein offensichtlicher Mangel dieses Modells ist, dass angenommen wird, sequentielles Lesen/Schreiben in Vorw¨artsrichtung w¨are genauso teuer wie Lesen/Schreiben in Ruckw¨ ¨artsrichtung, was auf einer rotierenden Spur sicher nicht der Fall ist. 19 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Kopfbewegung bildlich

Betrachten wir jetzt den Fall fur¨ Exquisit, wenn eine Datei F mit M Bl¨ocken geteilt wird.

1 2 3 . .. M − 2M − 1 M

. .

Abbildung 3: Kopfbewegung bei aufeinanderfolgenden Blockzugriffen von beiden Seiten der Datei

20 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren EXQUISIT bildlich I

Der genaue Wert fur¨ die Kopfbewegung, um M Bl¨ocke in einem bidirektionalem Durchgang zu teilen, h¨angt von verschiedenen Annahmen ab, einige davon sind recht willkurlich¨ gew¨ahlt. Zum einen nehmen wir an, dass die M Bl¨ocke abwechselnd vom linken und rechten Ende gelesen werden, d.h. nach jedem Lese-/Schreibvorgang kehrt der Kopf um und wandert an das andere Ende (siehe Anmerkung unten).

21 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren EXQUISIT bildlich II

Betrachten wir die Teilung einer Folge F . Der Kopf hat Block 1 gelesen und steht abstrakt gesehen am Ende des Blocks 1. Jetzt muss er uber¨ M − 1 Bl¨ocke wandern, um an den Anfang von Block M + 1 zu gelangen, also uber¨ die Folge F hinweg. Dort schreibt er den letzten Block zuruck,¨ der im Puffer war, bevor die Folge F zum Teilen dran kam. Das ist eben vermutlich Block M + 1.

22 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren EXQUISIT bildlich III

Danach steht der Kopf am Ende von Block M + 1. Um jetzt Block M zu lesen, muss der Kopf zwei Bl¨ocke zuruck¨ an den Anfang von M. Insgesamt kommt man damit auf eine Distanz von M + 1 Bl¨ocken. Nachdem Block M gelesen wurde, kehrt der Kopf zuruck¨ an den Anfang von Block 1, der jetzt uberschrieben¨ wird, gefolgt vom Lesen des Blocks 2 (null Distanz). Somit kostet die Ruckkehr¨ insgesamt M. Am Ende, wenn sich die Pointer in einem Block treffen, sparen wir 2 Zugriffe. Aus dieser Logik leiten sich dann Gesamtkosten von (M + 1)(M + 2)/2 − 2 Blockdistanzen fur¨ das Lesen und Schreiben von M Bl¨ocken ab.

23 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren EXQUISIT bildlich IV

Der Gesamtaufwand f (M) fur¨ die Kopfbewegung zur Sortierung einer Datei mit M Bl¨ocken l¨asst sich jetzt mit der ublichen¨ Rekursionsgleichung unter der Annahme gleichverteilter Trennpositionen berechnen. Sei g(M) der Aufwand zum Teilen der Folge F mit |F | = M, dann ben¨otigt Exquisit im Mittel

1 M−1 f (M) = g(M) + X (f (t) + f (M − t)) M t=1 Bl¨ocke fur¨ die Kopfbewegung. Fugt¨ man g(M) = (M + 1)(M + 2)/2 − 2 ein, ergibt sich

3M2 M f (M) = + 6(M − 1)H + − 3 2 M−2 2 = O(M2 + M ln M).

24 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Ein kritischer Blick auf die Analyse I

Fugt¨ man andere Absch¨atzungen fur¨ g(M) ein, ergeben sich ganz 3M2 ¨ahnliche Resultate, aber der fuhrende¨ Term 2 bleibt gleich! Somit erzeugt ein externer Quicksort mit einer einfachen bidirektionalen Teilephase in unserem linearen Modell Kopfdistanzen von O(M2). Rechtfertigt dies die Behauptung, Quicksort habe ein schlechtes Lokalit¨atsverhalten? Das l¨asst sich nur beantworten, wenn man andere Methoden zum Vergleich heranzieht. Ein offensichtlicher Konkurrent ist Mergesort.

25 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Ein kritischer Blick auf die Analyse II

 Eine fragwurdige¨ Annahme ist die vollst¨andige Umkehr des Kopfs nach jedem Lesen oder Schreiben eines Blocks. Zum einen hat jeder der zwei Bl¨ocke vom linken oder rechten Rand eine 50:50-Chance, zuerst ersetzt zu werden, wenn beide Durchg¨ange von links und rechts gleichzeitig starten. Deshalb ist der Kopf in der H¨alfte aller F¨alle immer noch an dem Ende, an dem die n¨achste Lese-/Schreiboperation verlangt wird.

26 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Pre-fetching doch nutzlich?¨ I

 Zweitens kann man leicht eine Strategie fur¨ vorausschauendes Laden (pre-fetching) entwerfen. Alles was man dazu braucht, sind zwei extra Puffer (einen extra fur¨ jede Seite) fur¨ nun zusammen vier Bl¨ocke2. Das Sortierverfahren merkt sich jetzt einfach den Index des letzten gelesenen oder geschriebenen Blocks. Nehmen wir an, der Kopf war zuletzt am linken Ende, und wir haben Block bi aufgebraucht (der Scan kommt am Ende des Blocks an). Sofern der zus¨atzliche Puffer nicht schon einen frischen Block bietet, mussen¨ wir jetzt Block bi+1 laden und vorausschauend dann auch bi+2.

27 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Pre-fetching doch nutzlich?¨ II

Der andere Fall tritt auf, wenn wir einen Block bj am rechten Ende aufgebraucht haben und Block bj−1 nicht schon im Puffer ist (alles unter der Annahme, dass der Kopf noch am linken Ende ist). Dann muss der Kopf jetzt nach rechts wandern, dort bj und bj+1 zuruckschreiben,¨ dann bj−1 laden und, wo wir schon gerade dran sind, vorausschauend auch bj−2. Dieselbe Geschichte wiederholt sich, wenn der Kopf zuletzt rechts gelesen oder geschrieben hat. Naturlich¨ l¨asst sich damit die Anzahl der Lese-/Schreibvorg¨ange nicht reduzieren, aber die Kopfdistanzen halbieren sich.

28 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Pre-fetching doch nutzlich?¨ III

Insgesamt stehen die Betrachtungen zu den Kopfdistanzen auf wackeligem Grund. Arbeitet die Platte in einer Mehrprozessumgebung, wird es wechselnde Zugriffe geben. Platten verwenden auch eine Sammelstrategie fur¨ Lese-/Schreibvorg¨ange, die so funktioniert wie ein Fahrstuhl. Anfragen werden umsortiert, damit der Arm mit allen K¨opfen vom ¨außersten Zylinder (dem Keller) bis zum innersten Zylinder (dem obersten Stock) wandern kann und erst dort umkehrt, wobei bei Auf- und Abfahrt alle zwischenliegenden Stockwerke, die angefragt hatten, bedient werden.

2Das steht im Gegensatz zu der Beobachtung von Verkamo in [Ver87]; siehe auch die Diskussion ab Folie 42. 29 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Mergesort als Mitbewerber

In [SW84] wurde ein p-Wege-Mergesort implementiert, der gegen Exquisit antrat. Die Mischordnung p wird wie folgt gew¨ahlt: Sei x die Dateigr¨oße, k die HS-Gr¨oße (gemessen in S¨atzen), und es x werden in der Initialisierungsphase des Mergesorts r ≤ d k e vorsortierte Folgen produziert. Mittels eines p-Wege-Mischens wird die Sortierung in dlogp(r)e Durchg¨angen fertiggestellt, wobei jeder x Durchgang d k e externe Lese- (und Schreib-)vorg¨ange ben¨otigt, b p+1 c da der HS in p gleich große Eingabepuffer und einen Ausgabepuffer aufgeteilt ist. Somit ergibt sich die optimale Mischordnung popt als der Wert, der die Anzahl der externen Lesevorg¨ange x dlogp(r)e · d k e b p+1 c minimiert.

30 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Gleiche Bedingungen fur¨ beide Verfahren

Fur¨ die Simulation und Messungen wird der interne Speicher als integer array S[1:2s] definiert3. In den Testl¨aufen wird s immer so gew¨ahlt, dass 2s ein Vielfaches von popt + 1 ist, d.h. 0 0 2s = (popt + 1) · s fur¨ ein s . Somit besteht die zu sortierende Datei aus M0 Bl¨ocken der Gr¨oße s0 dergestalt, dass M0 · s0 = M · s, wobei M und s die passenden Parameter in Exquisit sind. Die Datei und der externe Arbeitsbereich werden durch integer array E’[1:2M’, 1:s’] repr¨asentiert, und die Daten werden als logische Bl¨ocke der Gr¨oße s0 transferiert.

3In der Originalarbeit war N als Blockgr¨oße definiert. Hier nehmen wir s als Bezeichner, weil in der Vorlesung N fur¨ die Gesamtgr¨oße einer Datei (gemessen in S¨atzen) bei der Multimengenanalyse steht. 31 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Bildung von vorsortierten Folgen und Kopfdistanzen I

Der Mergesort beginnt wie ublich¨ mit der Bildung von sortierten Folgen der L¨ange 2s mittels Quicksort. Ist der letzte Schlussel¨ einer Folge ≤ dem ersten Schlussel¨ der n¨achsten Folge, werden sie zu einer uberlangen¨ Folge verbunden. Bei unseren Versuchsl¨aufen trat wegen der zuf¨alligen Permutation der S¨atze dieser Fall nie auf. Somit ist die Anzahl der vorsortierten Folgen immer

M0 · s0 M0 0 = . (popt + 1) · s popt + 1

32 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Bildung von vorsortierten Folgen und Kopfdistanzen II

Um die Kopfbewegungen fur¨ Mergesort absch¨atzen zu k¨onnen, nehmen wir an, dass popt aufeinanderfolgende Schreibvorg¨ange gefolgt werden von popt aufeinanderfolgenden Leseoperationen und umgekehrt, was eine optimistische Annahme ist. Ferner mischen wir in unserem linearen Blockmodell wechselweise aus der Datei F in die Datei F 0, und F 0 liegt direkt nach (oder direkt vor) F , jeweils mit Gr¨oße M Bl¨ocke. Mit anderen Worten, Verschr¨ankungen (inter-leaving) der Bl¨ocke4 wird nicht betrachtet (siehe Abb. 4).

4oder noch besser Mischen auf zwei Platten 33 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Kopfbewegung bei Mergesort bildlich

F F 0 1 2 ... M 1 2 ... M

Distanz M

Abbildung 4: Kopfbewegung bei Mergesort ohne Verschr¨ankung

34 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Kopfbewegung bei Mergesort analytisch

In jedem Durchgang wandert der Kopf 2M/popt -mal die Distanz M. Multipliziert mit der Anzahl an Durchl¨aufen, also mit 2 logpopt (M), kommen wir auf gesamt O(M logpopt (M)) Bl¨ocke fur¨ die Kopfbewegungen im Mergesort im linearen Blockmodell ohne Verschr¨ankung. Damit liegt Mergesort um den Faktor logp(M) uber¨ dem Wert fur¨ den externen Quicksort! Dieses analytische Resultat wird von den experimentellen Messungen best¨atigt (vgl. Tabellen unten).

35 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Simulationsergebnisse I

Die Simulationen wurden fur¨ eine Datei mit 2400 S¨atzen durchgefuhrt.¨ Diese Zahl wurde gew¨ahlt, weil sie sich leicht auf verschiedene HS-Gr¨oßen aufteilen l¨asst, andererseits groß genug ist, um die Effizienz beurteilen zu k¨onnen.

Der Hauptspeicherpuffer variiert von 12 bis 1200 S¨atzen. Somit passen zwischen 0,5 % und 50 % der Datei in den internen Speicher. Passend dazu werden M und s fur¨ Exquisit bzw. M0 0 0 und s fur¨ Mergesort so variiert, dass 2s bzw. (popt + 1) · s die HS-Gr¨oße ergibt. Damit gibt die NBR-Spalte die Anzahl der Blocklesevorg¨ange fur¨ Bl¨ocke der Gr¨oße s bzw. der Gr¨oße s0 an. Exquisit transferiert die Daten in gr¨oßeren Happen, außer in der Vorsortierungsphase des Mergesort, wo jede HS-Fullung¨ als ein Blocklesevorgang z¨ahlt.

36 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Simulationsergebnisse II

Im praktischen Gebrauch k¨onnte die geringfugig¨ kleinere Anzahl an Zugriffen (seeks) durch l¨angere Transferzeiten ausgeglichen werden. Fur¨ die Hauptspeichergr¨oßen 48 und 240 in der Mergesort-Tabelle beinhalten die Z¨ahlungen NBR/NBW und DHT ein Ruckkopieren¨ der Datei, da nach dem letzten Durchgang die Datei nicht am Ausgangsort zu liegen kam.

Man beachte auch, dass die DHT-Werte (distance of head travel) mit s bzw. mit s0multipliziert wurden, d.h. die Distanz wird in S¨atzen gemessen, was genauer ist, wenn M 6= M0.

37 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren EXQUISIT Messwerte

Tabelle 1: EXQUISIT mit ’(min(F) + max(F ))/2 Strategie’

M s HS Prozent NBR NBW DHT 400 6 12 0.5 % 3643 3540 779 490 200 12 24 1 % 1657 1642 444 336 100 24 48 2 % 728 722 247 344 40 60 120 5 % 215 210 107 280 20 120 240 10 % 86 84 59 760 10 240 480 20 % 35 34 35 520 4 600 1200 50 % 8 8 13 200

38 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren EXQUISIT Messwerte

Tabelle 2: EXQUISIT mit ’(firstkey + lastkey)/2 Strategie’

M s HS Prozent NBR NBW DHT 400 6 12 0.5 % 4262 3726 786 960 200 12 24 1 % 1953 1832 440 352 100 24 48 2 % 868 845 257 760 40 60 120 5 % 300 298 132 120 20 120 240 10 % 123 123 78 600 10 240 480 20 % 48 48 46 560 4 600 1200 50 % 12 12 19 800

39 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Mergesort Messwerte

Tabelle 3: Mergesort

M’ s’ HS Prozent NBR/NBW DHT popt 800 3 12 0.5 % 4200 15 911 952 3 600 4 24 1 % 1900 6 707 080 5 200 12 48 2 % 900 3 310 872 3 80 30 120 5 % 260 903 960 3 50 48 240 10 % 120 422 496 4 30 80 480 20 % 35 113 600 5 6 400 1200 50 % 8 34 400 2

40 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren EXQUISIT Nachtrag

Als Schlusswort sei hinzugefugt,¨ dass in unserer Experimentierumgebung die gemessenen Ausfuhrungszeiten¨ fur¨ Exquisit um 25 % unter denen von Mergesort lagen.

41 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Verkamos Beobachtung

Verkamo untersuchte das Verhalten interner Sortieralgorithmen, die in einer Umgebung mit virtuellem Speicher auf externe Dateien angewandt werden (siehe [Ver86]), und er betrachtet Varianten des Quicksort, die an externes Sortieren [Ver87] [Ver88] [Ver89] angepasst wurden, einschließlich unseres Verfahrens Exquisit. Ahnliche¨ Resultate finden sich in einem Artikel von Alanko, Erkioe und Haikala uber¨ Sortieren in virtuellem Speicher [TAH84].

42 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Verkamos zwei Phasen

Verkamo betrachtet in [Ver87], dass Quicksort zwei Phasen durchl¨auft (ohne scharfe Trennung): (1) scanning – Aufteilephase fur¨ lange Folgen, (2) completion – Fertigstellung fur¨ kurze Folgen. W¨ahrend der Phase (1) mehr als zwei Seiten im HS zu halten, bringt nichts, d.h. ein kleiner working set ist von Vorteil5. In Phase (2) ist jedoch ein großer working set gunstig,¨ da Seiten von bereits geteilten, kurzen Teilfolgen im HS gehalten werden. Die ubliche¨ LRU Seitenersetzungsstrategie sollte dabei helfen.

5Beachte aber unsere Uberlegungen¨ zu pre-fetching zur Reduzierung der Kopfdistanzen. 43 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Verkamos Vergleich I

Verkamo untermauert seine Argumente mit sehr anschaulichen Zugriffsmustern (hier nicht gezeigt). Die von ihm angegebenen Tabellen fur¨ vier Quicksort-Varianten fur¨ externes Sortieren haben wir ubernommen¨ aus [Ver87]. Der Vergleich enth¨alt Qsort: der original Quicksort, Psort: ein Quicksort mit variablen Puffergr¨oßen, Esort: Exquisit, Wsort: Quicksort kombiniert mit Mergesort.

44 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Verkamos Vergleich II

Tabelle 4: Parameterwerte.

file size (words) 1000, 2000, 5000, 10000, 20000 page size (words) 32, 64, 128, 256, 512, 1024 window size (refs) 1K, 2K, 4K, 8K, . . . , 1024K

45 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Verkamos Vergleich III

Tabelle 5: Optimale Fenstergr¨oßen fur¨ unterschiedliche Datei- und Seitengr¨oßen.

file size 1000 2000 5000 10000 20000 window Qsort: 32 1K 1K 1K 1K 1K 1K 64 2K 1K 1K 1K 1K 1K 128 2K 2K 2K 2K 2K 2K 256 16K 4K 4K 4K 4K 4K 512 16K 8K 8K 4K 4K 8K 1024 – 8K 8K 8K 4K 8K

46 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Verkamos Vergleich IV

file size 1000 2000 5000 10000 20000 window Wsort: 32 32K 16K 16K 16K 16K 16K 64 64K 32K 32K 32K 32K 32K 128 128K 64K 64K 64K 64K 64K 256 64K 32K 32K 32K 32K 32K 512 4K 2K 32K 32K 32K 32K 1024 – 2K 1K 1K 1K 1K

47 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Verkamos Vergleich V

Tabelle 6: Laufzeit und Anzahl der Seitenfehler.

Qsort Psort Esort Wsort N = 1000 proc. time: .345 .351 .398 .372–1.238 number of faults: p=32 258 80 209 141 p=64 129 39 84 57 p=128 54 19 32 26 p=256 23 9 9 21 p=512 5 4 2 11

48 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Verkamos Vergleich VI

Qsort Psort Esort Wsort N=10000 proc. time: 4.77 4.85 5.20 8.95–23.35 number of faults: p=32 4404 2279 3470 2398 p=64 2277 1138 1558 1061 p=128 1051 565 677 469 p=256 479 284 288 661 p=512 210 135 126 324 p=1024 105 65 49 243

49 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Verkamos Fazit

Esort liefert niedrigere Seitenfehler als z.B. Qsort, hat aber eine geringfugig¨ l¨angere Ausfuhrungszeit.¨ Psort hat extrem niedrige Seitenfehler aber nur geringfugig¨ bessere Laufzeiten. Wsort variiert sehr stark in den Laufzeiten.

50 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Der Monard-Algorithmus I

Gonnets Handbook of Algorithms and Data Structures enth¨alt einen Abschnitt uber¨ External Quicksort [Gon84, p. 160–162], der auf eine Arbeit von M.C. Monard [Mon80] zuruckgeht.¨ Die grundlegende Idee ist, einen sortierten Puffer der Gr¨oße k ≥ 3 anzulegen und damit die Teilung zu steuern, ¨ahnlich der “Verbesserung” durch van Emden [vE70b, vE70a]. Das Ergebnis eines Aufrufs von partition(l, r, i, j) ist eine Dreiwegeteilung mit einer sortierten Teilfolge F2 zwischen i + 1 und j − 1 (siehe Abb. 5).

F1 F2 F3 l i i + 1 j − 1 j r

| {z } | {z } | {z } alle≤R(i+1) sortiert alle≥R(j−1)

Abbildung 5: Endsituation nach Aufteilung F (l..r). 51 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Der Monard-Algorithmus II

Dazwischen ist die Situation so, wie in Abbildung 6 dargestellt. Der Algorithmus adjustiert i, gdw. Prozedur extract lower einen Satz rx mit rx .key < rlower bound .key zuruck¨ in die Datei schreibt, bzw. adjustiert j, gdw. extract upper einen Satz rx mit rx .key > rupper bound .key schreibt. lower bound upper bound <<< leer ? leer <<< l i j r extract lower extract upper

Puffer

Abbildung 6: Zwischensituation mit Transfer vom und zum Puffer.

52 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Monards Analyse

Monards Analyse liefert den bekannten Wert O(N2) fur¨ den schlechtesten Fall bei einer Datei mit N S¨atzen. Fur¨ das durchschnittliche Verhalten liefern sowohl die Originalarbeit von Monard als auch Gonnets Buch eine Laufzeit, die proportional ist zu

f¯(N) = a · N · ln N + O(N) mit 1 a = , H2K − HK was ungef¨ahr ln 2 ≈ 0, 693147 ist.

Fur¨ eine zehnseitige Analyse ist das ein schwaches Resultat, weil vermutlich der Blockverkehr nicht genugend¨ berucksichtigt¨ wurde.

53 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Gonnets Anzahl der Durchl¨aufe

Gonnet gibt aber eine empirische Formel fur¨ die zu erwartende Anzahl an Durchl¨aufen an: N  E [P ] = log − 0, 924 N 2 k

mit k die Puffergr¨oße (in S¨atzen). Das ergibt die bekannten Werte

O(N log M) fur¨ den E/A-Verkehr (in S¨atzen) und O(M log M) fur¨ den Seitenverkehr (in Seiten).

Gonnet schließt daraus, da der Algorithmus am Ort arbeitet, dass External Quicksort seems to be an ideal sorting routine for direct access files.[Gon84, p. 162]

54 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Zusammenfassung

Diese Sicht der Dinge unterscheidet sich deutlich von der Diskussion, mit der wir gestartet sind. Selbst wenn Quicksort nicht der ideale Kandidat ist, dann ist Quicksort immerhin eine ernsthafte Alternative fur¨ externes Sortieren bei wahlfreiem Zugriff.

Die beiden bekanntesten Vorteile von Quicksort, schnelle innere Schleifen und nur rund N/6 Vertauschungen, spielen keine so große Rolle beim externen Sortieren, weil sie nicht den E/A-Verkehr beeinflussen. Große interne Speicher, die heute ublich¨ sind, helfen wenig in der Anfangsphase beim Teilen, sind aber nutzlich¨ fur¨ kurze Teilfolgen am Ende. Uberlappendes¨ Lesen/Schreiben, smoothness fur¨ Multimengen und Vorsortierungen sowie Sicherung gegen Ausf¨alle w¨ahrend der Sortierung w¨aren Punkte, die man weiter untersuchen k¨onnte.

55 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Literatur I

[BGM70] Barbara S. Brawn, Frances G. Gustavson, and Efrem S. Mankin, Sorting in a paging environment, Commun. ACM 13 (1970), no. 8, 483–494. [CK80] C.R. Cook and D.J. Kim, Best sorting algorithms for nearly sorted lists, Communications of the ACM 23:11 23 (1980), 620–624. [Den68] P.J. Denning, The working set model program behavior, Communications of the ACM 3:5 (1968), 323–333. [Den80] , Working sets past and present, IEEE Transactions on Software Engineering SE-6:1 (1980), 64–84. [Gon84] Gaston H. Gonnet, Handbook of Algorithms and Data Structures, Addison-Wesley, 1984.

56 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Literatur II

[Knu98] Donald E. Knuth, The Art of Computer Programming. Vol. 3: Sorting and Searching, 2nd ed., vol. 3, Addison-Wesley, 1998. [Lor75] Harold Lorin, Sorting and sort systems, Addison Wesley, 1975. [Mon80] M.C. Monard, Design and analysis of external quicksort algorithms, Ph.D. thesis, PUC University, Rio de Janeiro - Brazil, 1980. [Pet74] J.G. Peters, The effects of paging on sorting algorithms, Tech. report, Dept. of Applied Analysis and Computer Science, University of Waterloo, Ontario, Canada, August 1974.

57 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Literatur III

[Sed78] Robert Sedgewick, Implementing quicksort programs, Commun. ACM 21 (1978), no. 10, 847–857. [Sha85] P. Shackelton, Correspondence on – sorting a random access file in situ, The Computer Journal 27:3 (1985), 270–275. [SW84] Hans-Werner Six and Lutz M. Wegner, Sorting a random access file in situ, The Computer Journal 27 (1984), no. 3, 270–275. [TAH84] H. H. A. Erkioe T.O. Alanka and I. J. Haikala, Virtual memory behavior of some sorting algorithms, IEEE TSE SE 10 No. 4 (1984), 422–431.

58 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Literatur IV

[vE70a] Maarten H. van Emden, Algorithms 402: Increasing the efficiency of quicksort, Commun. ACM 13 (1970), no. 11, 693–694. [vE70b] , Increasing the efficiency of quicksort, Commun. ACM 13 (1970), no. 9, 563–567. [Ver86] A. Inkeri Verkamo, Comparison of external sorting and internal sorting in virtual memory, Perform. Eval. 6 (1986), no. 2, 135–145. [Ver87] , Performance of quicksort adapted for virtual memory use, Comput. J. 30 (1987), no. 4, 362–371. [Ver88] , External quicksort, Perform. Eval. 8 (1988), no. 4, 271–288.

59 / 60 Besonderheiten externer Sortierverfahren EXQUISIT - Ein externer Quicksort Andere externe Sortierverfahren Literatur V

[Ver89] , Performance comparison of distributive and mergesort as external sorting algorithms, Journal of Systems and Software 10 (1989), no. 3, 187–200. [Wai85] R.L. Wainwright, A class of sorting algorithms based on quicksort, Communications of the ACM 28:4 (1985), 396–402. [Wal77] H. Waldschmidt, Sortieren bei virtuellem Speicher, Computing 19 (1977), 1–14.

60 / 60 Sortieren in einem Netzwerk Verteiltes Sortieren Quicksort im Netz Vergleich und Fazit

Sortierverfahren Quicksort in einem Netzwerk

Lutz Wegner

12. Juni 2014

1 / 26 Sortieren in einem Netzwerk Verteiltes Sortieren Quicksort im Netz Vergleich und Fazit Inhaltsverzeichnis

1 Sortieren in einem Netzwerk Anwendung und Alternativen

2 Verteiltes Sortieren Die RSS-Methode

3 Quicksort im Netz Grundidee Aufteilungsposition berechnen Botschaftenaustausch Analyse

4 Vergleich und Fazit Experimentelle Ergebnisse Zusammenfassung

2 / 26 Sortieren in einem Netzwerk Verteiltes Sortieren Quicksort im Netz Vergleich und Fazit Zwei Netzwerkl¨osungen fur¨ die Sortieraufgabe

In dieser Lektion schauen wir uns zwei Netzwerkl¨osungen fur¨ eine Sortieraufgabe an: ein Verfahren von L. Wegner [Weg84] und eines von D. Rotem, N. Santoro und J.B. Sidney [DRS85].

3 / 26 Sortieren in einem Netzwerk Verteiltes Sortieren Quicksort im Netz Vergleich und Fazit Aufgabenstellung

Netzwerksortieren betrifft hier große Dateien, die uber¨ M Stationen (hosts) verteilt sind, die mittels eines Netzwerks (LAN, WAN) miteinander verbunden sind, z.B. ein landesweites Bibliothekssystem, eine Buroumgebung¨ mit Lastverteilung oder M Platten, die an M Prozessoren h¨angen. Wir betrachten nicht Sortiernetzwerke, wie z.B. den Bitonic Sorter, da ihnen ein anderes Rechnermodell zugrunde liegt.

Sei N wie gewohnt die Gr¨oße der Datei in S¨atzen, sei M jetzt die Anzahl der Stationen mit ni S¨atzen in Station i. Oft betrachten wir den Spezialfall ni = n = N/M ∀(1 ≤ i ≤ M).

4 / 26 Sortieren in einem Netzwerk Verteiltes Sortieren Quicksort im Netz Vergleich und Fazit Beispiel Autovermietung I

Beispiel Betrachten wir eine Autovermietung. Zu sortieren sind 13 500 S¨atze, jeder 1 000 Bytes lang. Die Dateigr¨oße ist dann ca. 13,5 MB. Gegeben seien 350 Stationen, verbunden mit langsamen 64 kBit/s Leitungen und einer Paketzustellzeit von 300 ms. Fur¨ die beiden Verfahren (W ≡ Wegner, RSS ≡ Rotem/Santoro/Sidney), die wir betrachten, wurden¨ wir die folgenden Ausfuhrungszeiten¨ erwartena.

a log M taucht in beiden Absch¨atzungen auf, hier log2 350 ≈ 8, 45.

5 / 26 Sortieren in einem Netzwerk Verteiltes Sortieren Quicksort im Netz Vergleich und Fazit Beispiel Autovermietung II

Beispiel (Forts.)

Tabelle 1: Sortierzeit beeinflusst von Datenfluss- und Ubertragungszeit.¨

Autoren asympt. Verhalten Datenvolumen/ Zeit Botschaften Datenfluss W N log M 114 MB 4 h RSS N 13,5 MB 30 min Botschaften W M log M 2957 14,7 min RSS M2 log M 1035125 86,5 h

6 / 26 Sortieren in einem Netzwerk Verteiltes Sortieren Quicksort im Netz Vergleich und Fazit Grunds¨atzliche Alternativen

Tabelle 2: Netzwerksortieren

Methode Botschaften Datenfluss Vergleiche extra Platz

zentral 2M 2N N log NN Interpolation M2 N 2N log n n (1 Station) iter. Merging M2 M · NN log n + 2MN 2n · M = 2N [Weg84] M log MN log MN log NM (bei 1 Stat.) [DRS85] M2 log M max{N, M2 log M} ? M2

7 / 26 Sortieren in einem Netzwerk Verteiltes Sortieren Quicksort im Netz Vergleich und Fazit Verteiltes Sortieren – die RSS-Methode I

Die Sortiermethode von Rotem, Santoro und Sidney ist ¨ahnlich einer Interpolationsverteilung, arbeitet aber in zwei Schritten:

(1) fur¨ i = 1, 2,..., M − 1 finde den ki -kleinsten Schlussel¨ (alle S¨atze die in Station i sollen), aber ohne tats¨achlich die S¨atze schon zu verteilen;

(2) verteile alle S¨atze gem¨aß den berechneten Werten ki (bedeutet im Mittel Daten an alle anderen zu verschicken und von allen anderen zu empfangen).

8 / 26 Sortieren in einem Netzwerk Verteiltes Sortieren Quicksort im Netz Vergleich und Fazit Verteiltes Sortieren – die RSS-Methode II

Schritt (1) verlangt M2 log(N) Botschaftenpaare h¨ochstens M2 log(M) Botschaftenpaare im Mittel Schritt (2) verlangt M2 Botschaften N Datenfluss (Anzahl gesendeter S¨atze) Rotem, Santoro und Sidney behaupten, dass ihre Methode optimal fur¨ den schlechtesten Fall ist (worst case optimal).

9 / 26 Sortieren in einem Netzwerk Verteiltes Sortieren Quicksort im Netz Vergleich und Fazit Quicksort angepasst an Netzwerkumgebung

Wegners Vorschlag geht auf Quicksort zuruck,¨ ist also eine Teile-und-herrsche-Methode, wird aber so angepasst dass - keine Schlusselvergleiche¨ zwischen Stationen stattfinden - der Datenverkehr in großen Bl¨ocken geschieht - alle Stationen gleichzeitig besch¨aftigt sind (Beschleunigung durch Parallelisierung) - wenig Verwaltungsaufwand zur Steuerung anf¨allt - die Routenplanung (wer schickt was wohin) einfach bleibt - kein extra Platz notwendig wird (in situ sorting)

10 / 26 Sortieren in einem Netzwerk Verteiltes Sortieren Quicksort im Netz Vergleich und Fazit Implementierungsdetails I

Ursprunglich¨ “geh¨oren” alle Stationen zur Datei F (die Datei F verteilt sich auf alle M Stationen). Jede Station i fuhrt¨ eine Median-von-drei-Pivotwahl durch und liefert den gefundenen Schlusselwert¨ Hi an den Koordinator (z.B. eine der Stationen). Der Koordinator berechnet einen Pivotwert H aus den gelieferten Hi , z.B. als Median oder Durchschnitt. Dieser Wert H wird an alle Stationen ubermittelt¨ (broadcast to all stations).

11 / 26 Sortieren in einem Netzwerk Verteiltes Sortieren Quicksort im Netz Vergleich und Fazit Implementierungsdetails II

Jede Station teilt jetzt ihre S¨atze gem¨aß dem empfangenen Pivotwert H mit der normalen Teile-und-tausche-Methode von Quicksort. Jede Station teilt dem Koordinator dann mit, wie viele Schlussel¨ kleiner oder gleich H und wie viele gr¨oßer H sind. Der Koordinator summiert diese Zahlen und berechnet daraus die globale Splitposition fur¨ die Teilfolgen F1 und F2, sagen wir Position p in Station k (vgl. Beispiel in Abbildung 1).

12 / 26 Sortieren in einem Netzwerk Verteiltes Sortieren Quicksort im Netz Vergleich und Fazit Aufteilung bildlich

Station k

Station k − 1 ≤ > Station k + 1

≤ > 1 p nk ≤ > Station k − 2 Station k + 2 #lows H ≤ > ≤ >

P lows = . . . ⇒ pivot position(Fi ) = (k, p)

Abbildung 1: Funf¨ Stationen teilen eine Teilfolge.

13 / 26 Sortieren in einem Netzwerk Verteiltes Sortieren Quicksort im Netz Vergleich und Fazit Botschaftenaustausch I

Wir haben jetzt k − 1 Stationen, die S¨atze loswerden mussen¨ mit Schlusseln¨ > H, und M − k Stationen, die S¨atze verlieren wollen, die Schlussel¨ ≤ H haben. Dies geschieht durch paarweisen Austausch zwischen Stationen “links” von k und denen “oberhalb” von k. Zun¨achst vermutet man, es w¨are gut, optimal passende P¨archen zu finden, aber das ist nicht n¨otig. Tats¨achlich w¨are das Problem der botschaftenoptimalen Paarbildung auch schwach NP-vollst¨andig. Der Beweis dazu fuhrt¨ man uber¨ die Ruckf¨ uhrung¨ auf das Subset-Sum-Problem.

14 / 26 Sortieren in einem Netzwerk Verteiltes Sortieren Quicksort im Netz Vergleich und Fazit Botschaftenaustausch II

Vielmehr genugt¨ es, den paarweisen Austausch zwischen zwei Stationen i und j so zu organisieren, dass der ausgetauschte Block die Gr¨oße s = min(what i wants to send, what j wants to send) hat. Das ben¨otigt 2 Botschaften der Gr¨oße s. Eine Station (diejenige, die s S¨atze loswerden will) ist damit fertig, sagen wir Station i. Die andere, also Station j, hat einen Rest und tauscht sich jetzt mit dem Nachfolger i + 1 aus. Dies l¨auft durch, bis F1 und F2 durch den letzten Tausch innerhalb der Station k gebildet wurden. Daraus folgt sofort das erste Lemma auf der folgenden Folie 16.

15 / 26 Sortieren in einem Netzwerk Verteiltes Sortieren Quicksort im Netz Vergleich und Fazit Analyse

Lemma Um eine Folge, die uber¨ M Stationen verteilt ist, aufzuteilen, ben¨otigt man h¨ochstens 2(M − 1) Botschaften.

Beweis. Jedes Paar von Botschaften schließt mindestens eine Station ab. Damit gilt ( f (x − 1, y) + 2 fur¨ x > 1 f (x, y) = f (x, y − 1) + 2 fur¨ y > 1

mit f (1, 1) = 2 und M = x + y.

16 / 26 Sortieren in einem Netzwerk Verteiltes Sortieren Quicksort im Netz Vergleich und Fazit Anzahl der Stationen fur¨ eine zuf¨allige Folge

Lemma Die erwartete Anzahl an Stationen fur¨ eine zuf¨allige Teilfolge der L¨ange N belegt N − 1 + 1 n Stationen, wobei n die einheitliche Stationsgr¨oße ist.

Beweis. Summiert man uber¨ alle gleich wahrscheinlichen Startpositionen in der ersten Station, ergibt sich, dass die Folge eine Station mehr belegt (in eine weitere Station hineinragt), als sie gem¨aß Gr¨oße rechnerisch br¨auchte.

17 / 26 Sortieren in einem Netzwerk Verteiltes Sortieren Quicksort im Netz Vergleich und Fazit Keine Lektion ohne Rekursionsgleichung! I

Die Anzahl der Botschaften, die man braucht, um die verteilte Datei der Gr¨oße N mittels des Netzwerk-Quicksorts zu sortieren, ergibt sich aus der allgemeinen Rekursionsgleichung fur¨ N > n und dem Faktor 2 aus dem Lemma auf Folie 16. X S(N) = 2(N − 1)/n + (pk S(k) + pN−k S(N − k)) 1≤k≤N−1

wobei pk die Wahrscheinlichkeit ist, dass eine Teilfolge der L¨ange k entsteht.

18 / 26 Sortieren in einem Netzwerk Verteiltes Sortieren Quicksort im Netz Vergleich und Fazit Keine Lektion ohne Rekursionsgleichung! II

Mit einfacher Pivotwahl bekommen wir 2 S(N) = 2(N − 1)/n + X S(k) mit S(n) = 0, N was zu

4(N + 1) 8 4(N + 1) S(N) = (H − H ) + − n N n+1 n n(n + 1)

fuhrt.¨ Mit der ublichen¨ Absch¨atzung fur¨ die harmonische Folge ergibt das

 1  8 4M S(N) = S(n · M) ≈ 4M ln M + 0.57721 + + − . 2M n n + 1

19 / 26 Sortieren in einem Netzwerk Verteiltes Sortieren Quicksort im Netz Vergleich und Fazit Analyse Vertauschungen

Genauso ist die Anzahl der paarweisen Vertauschungen N + 1 n − 1 S(N) = · , n + 2 n was im Grunde gerade die Anzahl der Stationen M ist. Alternativ, mit perfekter Pivotwahl, wird die Rekursionsgleichung zu

S(N) = 2(N − 1)/n + 2S(N/2),

was sich fur¨ N > n zusammenschieben l¨asst zu

S(N) = 2M log2 M − 2M − 2M/n + 2/n.

20 / 26 Sortieren in einem Netzwerk Verteiltes Sortieren Quicksort im Netz Vergleich und Fazit Analyse Datenfluss

Der zugeh¨orige Datenfluss ergibt sich daraus, dass wir in jeder der log2 M Teilungsrunden im Mittel die H¨alfte aller N S¨atze verschicken. Dies ergibt einen Datenfluss von N log M 2 2 S¨atzen.

Zur Erg¨anzung der Analyse geben wir das Ergebnis einer experimentellen Uberpr¨ ufung¨ in Tabelle 3 wieder.

21 / 26 Sortieren in einem Netzwerk Verteiltes Sortieren Quicksort im Netz Vergleich und Fazit Messung (Zeit in Sekunden)

Tabelle 3: Teile-tausche versus Zweischritt-Verteilung. M n Zeit Runden paarw. Vert. Botschaften Datenfluss [Weg84] 2 512 12,23 3 1 10 1666 8 128 12,48 5 6 82 2258 32 32 13,21 7 31 462 3900 128 8 19,16 9 112 2044 4806 512 2 37,54 11 232 5234 5462 [DRS85] 2 512 23,70 2 524 8 128 17,18 56 886 32 32 12,24 609 995 128 8 8,46 983 1018 512 2 2,85 1019 1024

22 / 26 Sortieren in einem Netzwerk Verteiltes Sortieren Quicksort im Netz Vergleich und Fazit Zusammenfassung

Zusammengefasst bringt Wegners Teile-tausche-Verfahren die S¨atze in mehreren Sprungen¨ an ihr Ziel. Dies fuhrt¨ zu einer zunehmend hohen Anzahl an Botschaften und einem hohen Datenfluss, wenn die Anzahl der Stationen steigt. Positiv zu vermerken ist, dass die Koordination einfach ist und die sp¨ateren Runden gut parallel ablaufen k¨onnen. Rotem, Santoro und Sidney bewegen jeden Satz nur einmal. Damit ist der Datenfluss im Grunde N. Die Anzahl der Botschaften wird O(M2) wenn M ≈ n und damit jede Station an beinahe jede andere S¨atze weggibt. Im Fall vieler Stationen mit wenigen S¨atzen, verh¨alt sich das Verfahren fast wie ein Pointersort. Umgekehrt, im Fall weniger Stationen, ist der Verwaltungsaufwand hoch und fuhrt¨ zu uberraschend¨ hohen Laufzeiten.

23 / 26 Sortieren in einem Netzwerk Verteiltes Sortieren Quicksort im Netz Vergleich und Fazit Hinweis zum Stoff der Vorlesung I

Wir beenden die Behandlung von Quicksort und seiner Varianten hier. Die stapellosen Quicksorts aus dem Turku-Skript sind eher kurios als nutzlich.¨ Durch geschicktes Tauschen von Schlusseln¨ kann man an die Enden der noch zu sortierenden Folgen Stopper einbauen und damit rein iterativ ohne jeglichen Stapel arbeiten. In der deutschen Wikipedia wird auf einen stabilen Quicksort fur¨ Arrays verwiesen, der in O(N log2 N) Schritten laufen soll. http: //h2database.googlecode.com/svn/trunk/h2/src/ tools/org/h2/dev/sort/InPlaceStableQuicksort.java. Es w¨are interessant, dieser Implementierung mal auf den Zahn zu fuhlen.¨

24 / 26 Sortieren in einem Netzwerk Verteiltes Sortieren Quicksort im Netz Vergleich und Fazit Hinweis zum Stoff der Vorlesung II

Im 12. Kapitel des Turku-Skripts wird auf die Webseite von David R. Martin verwiesen, die sich mit Sortieralgorithmen besch¨aftigt. Dort werden auch Dreiwege-Quicksorts behandelt [Mar07], darunter ein Verweis auf die Java core library mit einer Variante, die mit zwei Pivotelementen arbeitet. Sie stammt von Vladimir Yaroslavskiy [Yar09].

Seien die Pivotelemente P1 und P2, dann erzielt er eine Dreiwegeaufteilung, in der die erste Teilfolge alle S¨atze mit Schlusselwerten¨ < P1 und in der mittleren Teilfolge alle S¨atze mit Schlusselwerten¨ k stehen, so dass P1 ≤ k ≤ P2. Die rechte Teilfolge hat dann S¨atze mit Schlusseln¨ > P2. In einer pers¨onlichen Mail auf dieser Seite stellt Jon Bentley diese Erfindung auf eine Ebene mit der Originalidee fur¨ Quicksort durch Tony Hoare und die Analyse durch Sedgewick.

25 / 26 Sortieren in einem Netzwerk Verteiltes Sortieren Quicksort im Netz Vergleich und Fazit Literatur

[DRS85] N. Santoro D. Rotem and J.B. Sidney, Distributed sorting, IEEE TSE C-34, 4 (1985), 372–376. [Mar07] David R. Martin, Quick sort (3 way partition), 2007, [Online; accessed 28-May-2013]. [Weg84] Lutz Wegner, Sorting a distributed file in a network, Computer Networks 8 (1984), 451–461. [Yar09] Vladimir Yaroslavskiy, Replacement of quicksort in java.util.arrays with new dual-pivot quicksort, 2009, [Online; accessed 28-May-2013].

26 / 26 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte

Sortierverfahren Heapsort

Lutz Wegner

26. Juni 2014

1 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Inhaltsverzeichnis

1 Das nie endende Wunder des Heap Der einfache Heapsort Implementierung Analyse 2 Floyds Verbesserung Prinzip Analyse Das Programm zu Floyds Verbesserung 3 Variationen und offene Aspekte Minimum-Heap Den k-gr¨oßten Schlussel¨ finden Min-Max-Heaps Median und k-gr¨oßter Schlussel¨ Stabilit¨at Deapsort – Duplikatseliminierung mit Heaps

2 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Heap als Datenstruktur

Ein Heap als Datenstruktur ist ein vollst¨andiger Bin¨arbaum, der in einem Array so gespeichert wird, dass jeder Knoten ≥ seiner S¨ohne ist (vgl. Abbildung 1).

3 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Beispiel

100 90 70 50 80 60 40 20 10 30

100

90 70

50 80 60 40

20 10 30

Abbildung 1: Zehn zuf¨allige Knoten als Heap.

4 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Heap im Array

Insbesondere befinden sich die S¨ohne eines Knotens an der Position i an den Positionen 2i und 2i + 1. Im Grunde hat man damit eine Priorit¨atswarteschlange, in die man ein Element mit gegebener Priorit¨at mittels einer sift-down-Routine einfugt¨ und aus der man das Element mit maximaler Priorit¨at an der Wurzel herausnimmt. Daraus l¨asst sich leicht ein Sortierverfahren ableiten.

Die Originalver¨offentlichungen stammen von J.W.J. Williams [Wil64] (Heapsort) und R.W. Floyd [Flo64] (Treesort). Eine Lehrbuchversion von Heapsort folgt in Listing 2.

5 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte

Listing 1: Interner Heapsort als Pascal-Programm. { Heapsort as an internal sorting method. } { It sorts the array a from 1 to r. } procedure h e a p s o r t ( var a: sequence; r: index); var i : i n d e x ; t : e n t r y ;

procedure s i f t ( var a: sequence; i, r: index); { Let a[i] sink into heap which ends at a[r]. } var j : i n d e x ; t : e n t r y ; begin while 2 ∗ i <= r do {a[i] has a left son } begin j := 2 ∗ i ; i f j < r

6 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte

then {a[i] has a right son } i f a [ j ] . key < a [ j +1]. key then j := j + 1 ; { right son greater } i f a [ i ] . key < a [ j ] . key then {swap} begin t := a[i]; a[i] := a[j]; a[j] := t; i := j { keep on sifting } end e l s e i := r { heap has been reconstructed } end { w h i l e } end { s i f t }

7 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte

begin { h e a p s o r t } f o r i := r div 2 downto 1 do sift(a, i, r); { sort by extracting contin. maximum} f o r i := r downto 2 do begin t := a[i]; a[i] := a[1]; a[1] := t; s i f t ( a , 1 , i −1) end end { h e a p s o r t }

8 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Williams Vorschlag

Das Prinzip fur¨ Heapsort [Wil64] besteht darin, 1) den Heap von unten nach oben aufzubauen (eigentlich von Floyd [Flo64] vorgeschlagen) und 2) die Wurzel zu entfernen und dafur¨ dort das rechteste Blatt einzufugen,¨ was dann herabsinkt, bis die Heapeigenschaft wieder hergestellt ist. Fur¨ den ersten Teil errechnet man das Verhalten im schlechtesten Fall wie folgt: - N/2 Schlussel¨ sinken gar nicht ein, - N/4 Schlussel¨ sinken h¨ochstens 1 Ebene, - N/8 Schlussel¨ sinken h¨ochstens 2 Ebenen, - N/16 Schlussel¨ sinken h¨ochstens 3 Ebenen, - ...

- N/N = 1 Schlussel¨ sinkt h¨ochstens blog2 Nc Ebenen.

9 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Ebenen in der ersten Phase

Formal ergibt sich die Anzahl der Abstiegsschritte (Ebenen) in der ersten Phase zu1

blog Nc " # 2 N x i x 1 X (i − 1) = N X − X mit x = blog Nc 2i 2i 2i 2 i=1 i=1 i=1

= 2N − blog2 Nc − 2 − (N − 1)

= N − blog2 Nc − 1 ≤ N.

1siehe dazu den Anhang im Turku-Skript 10 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Schlechtester Fall fur¨ die zweite Phase

Was die zweite Phase anbetrifft, so fugen¨ wir im schlechtesten Fall N-mal einen Schlussel¨ in einen Heap der Gr¨oße 2,..., N − 1 ein, was h¨ochstens 2 * maximale-Pfadl¨ange viele Schlusselvergleiche¨ ben¨otigt [Knu73, p. 155]:

N   X blog2 Nc+1 2 · blog2 ic = 2 · (N + 1)blog2 Nc − 2 + 2 i=2

≈ 2Nblog2 Nc + 2blog2 Nc − 4N + 4.

11 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Verhalten im Durchschnitt fur¨ die zweite Phase

Die Analyse des durchschnittlichen Verhaltens der Selektionsphase fur¨ den Heapsort ... is another story, which remains to be written! [Knu73, p. 156][Knu98, p. 155]

Tats¨achlich gibt Knuth aber recht gute Sch¨atzungen in der ersten Auflage an und fugt¨ weitere in der zweiten Auflage hinzu. Diese gehen auf R. Schaffer und R. Sedgewick zuruck.¨ Bereits Gonnets Handbuch [Gon84, p. 128] gab die durchschnittliche Anzahl an Schlusselvergleichen¨ an mit

E[CN ] = 2N log2 N − 3, 0250N.

Die Durchschnittswerte bei Knuth [Knu73, pp. 148-157] sieht man in der folgenden Tabelle.

12 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Analysewerte nach Knuth

Tabelle 1: Werte aus Knuth [Knu73, pp. 148-157]

Gr¨oße Aufbau Auswahl Gesamt P, sift-up bN/2c − 1 N − 1 N + bN/2c − 2 Durchg. A, Einfugung¨ 0, 1967N ± 0, 3 0, 152N 0, 349N endet als inner. Knoten B, aufsteigende 0, 74403N − 1, 3 ln NN log N − 2, 61NN log N − 1, 87N Schlussel¨ 1 1 C, F¨alle mit 0, 47034N − 0, 8 ln N 2 N log N − 1, 4N 2 N log N − 0, 9N rechter Sohn > li. Sohn D, kein rechter 1, 8 ± 0, 2 fur¨ N gerade ln N ± 2 ln N Sohn 0 fur¨ N ungerade

13 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Obere Schranken

Fur¨ die Werte A, B und C aus der Tabelle gibt Knuth die folgenden oberen Schranken an: A ≤ 1, 5N, B ≤ Nblog Nc, C ≤ Nblog Nc.

14 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Die Floyd-Verbesserung

In Ubung¨ 18 fragt Knuth nach einer Verbesserung fur¨ Heapsort, die auf R. W. Floyd [Knu73, p. 158] zuruckgeht.¨ Da wir ein Blatt an der Wurzel einfugen,¨ wird dieses sehr wahrscheinlich bis zum Rand des Heaps absinken. Die Verbesserung besteht darin, ein “Loch” absinken zu lassen, was auf jeder Ebene nur einen Schlusselvergleich¨ (welcher Sohn ist gr¨oßer?) ben¨otigt!

15 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Beispiel

310 300

300 290 280

270 260 240 290 230 ...... 200 190 170 220 230 80 100 180 90 130 20 100 60 110 40 140 50 80 100 80 70 10 Abbildung 2: Entfernen 310 und Einfugen¨ 100.

16 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Pfad maximaler S¨ohne

Der Schlusselbegriff¨ ist der Pfad maximaler S¨ohne, entlang dem das Loch bis auf die Blattebene absinkt. Die Wahrscheinlichkeiten, dass das dort eingefugte¨ Blatt i Ebenen aufsteigt sind [Knu73, p. 619, Antwort zu Ubung¨ 18]: i = 0 : 0,848 i = 1 : 0,135 i = 2 : 0,016

17 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Was die Verbesserung bringt

Diese Methode, ein Loch absinken zu lassen, halbiert die Anzahl der Schlusselvergleiche¨ und verbessert die asymptotische Laufzeit von 16N log N + 0, 2N zu 13N log N + O(N). Bei eigenen Experimenten fur¨ diese Vorlesung mit N = 10 Mio. S¨atzen erzielten wir in einer Pascal-Implementierung eine Verbesserung von rund 434 Mio. Schlusselvergleichen¨ und 5,4 s Laufzeit auf rund 236 Mio. Schlusselvergleiche¨ und 3,9 s Laufzeit.

Weil man den Algorithmus fur¨ diese Verbesserung selten sieht, geben wir ihn auf den folgenden Folien an. Der Code wurde aus einem C-Programm, das Jukka Teuhola auf der Web-Seite [Teu93] ver¨offentlicht hat, ubertragen.¨ Wir kommen darauf im Zusammenhang mit Heapsort als externes Sortierverfahren nochmals zuruck.¨

18 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte

Listing 2: Heapsort mit Floyd-Verbesserung als Pascal-Programm. { Floyd−Verbesserung: Loch absinken lassen } { bis Blattniveau , neuen Knoten von dort } { aufsteigen lassen. } procedure s i f t U p ( var a: sequence; i, n: longint); l a b e l 9 9 ; var start, j: longint; x : item ; begin s t a r t := i ; x := a [ i ] ; j := i ∗ 2 ; while j <= n do begin i f j < n then begin

19 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte

i f a [ j ] . key < a [ j + 1 ] . key then i n c ( j ) ; end ; {a[j] is larger child } a[i] := a[j]; i := j; j := i ∗ 2 ; end ; j := i div 2 ; while j >= s t a r t do begin i f a [ j ] . key < x . key then begin a[i] := a[j]; i := j ; j := i div 2 end e l s e { break } goto 99 end ; 9 9 : a [ i ] := x end { o f s i f t −up} ;

20 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte

procedure FHeapsort ( var a: sequence; n: longint); var k : l o n g i n t ; x : item ; begin f o r k := n div 2 downto 2 do siftUp(a, k, n); { heap constructed bottom up} f o r k := n downto 2 do begin siftUp(a, 1, k); x := a [ 1 ] ; a[1] := a[k]; a [ k ] := x ; end ; end ;

21 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Der Min-Heap

Wir betrachten einige Variationen zum Thema Heapsort ohne Anspruch auf Vollst¨andigkeit. Die erste Variation ist ein Heap mit dem Minimum an der Wurzel – eigentlich eine “triviale” Modifikation, die aber knifflig zu programmieren ist. Unsere Version mit Namen Meapsort geben wir im Listing 3 an.

22 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Meapsort I

Listing 3: Meapsort {MEAPSORT} {A modified version of heapsort is shown. } { It has the minimum at its root and the } { root is to the right. This sort is used } { for sorting pages in algorithm hillsort. } { Its input is an array a from 1 to r. } {The secret formula for converting an index i } { in heapsort into j in meapsort is j=r−i +1.}

procedure meapsort ( var a: sequence; r: index); var i : i n d e x ; t : e n t r y ;

23 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Meapsort II

procedure s i f t ( var a: sequence; i, k: index); { let a[k] sink into its proper position in } { the heap ending at a[i], i.e. k is the } { right end, i the leftmost leaf. The array } { stretches from 1 to r. } var j : i n d e x ; t : e n t r y ; begin while 2 ∗ k − r >= i do {a[k] has a son } begin j := 2 ∗ k − r ; { j on son with larger index } i f j > i then {a[i] has a right son } i f a [ j ] . key > a [ j −1]. key

24 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Meapsort III

then j := j − 1 ; { smaller index son has smaller key } i f a [ k ] . key > a [ j ] . key then {swap because father is bigger } begin t := a[k]; a[k] := a[j]; a[j] := t; k := j { keep on sifting } end e l s e k := 0 { heap has been reconstructed } end { w h i l e } end { s i f t } ;

25 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Meapsort IV

begin { meapsort } f o r i := r − ( r div 2) + 1 to r do sift(a, 1, i); { sort now by extracting contin. the minimum} f o r i := 1 to r −1 do begin t := a[i]; a[i] := a[r]; a[r] := t; sift(a, i+1, r) end end { meapsort }

26 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Den k-gr¨oßten Schlussel¨ finden

Statt die Eingabe komplett zu sortieren, suche man nach den kleinsten (gr¨oßten) k Schlusseln:¨ - baue einen Heap auf =⇒ O(N) Schritte - entferne k-mal die Wurzel =⇒ O(k · log N) Schritte

27 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Min-Max-Heaps

M.D. Atkinson, J.R. Sack, N. Santoro und T. Strothotte [ASSS86] betrachten Min-Max-Heaps als generalisierte Priorit¨ats- warteschlangen. So eine Struktur ist nutzlich,¨ wenn man sowohl den maximalen als auch den minimalen Wert braucht, etwa in einem Puffer mit begrenztem Platz, der Botschaften aufnimmt. Wir suchen die dringendste Nachricht und die unwichtigste, weil wir Platz schaffen mussen¨ fur¨ eine neue eingehende Nachricht.

Ein Heap, der dies leistet, sieht man in Abbildung 3, die obigem Artikel entnommen wurde. Man erkennt gut die alternierenden Min-Max-Ebenen.

28 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Min-Max-Heaps

5

65 80

25 37 8 15

57 36 45 59 20 14 32 18

28 30 34 27 39 38 45 50 15 12 13 10 30 31 16 17 Abbildung 3: Ein Min-Max-Heap mit alternierenden Min-Max-Ebenen.

29 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Median und k-gr¨oßter Schlussel¨

Besteht die Aufgabe darin, den Median oder – allgemein – k-gr¨oßten Schlussel¨ einzufugen,¨ zu finden oder zu entfernen, sind Datenstrukturen wie der Heap sehr praktisch (vgl. Abbildung 4).

root k

all keys ≤ a[k] all keys ≥ a[k]

| {z }| {z } max−heap min−heap

Abbildung 4: Der k-gr¨oßte Schlussel¨ in einem Array a.

30 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Max- und Min-Heap im Zusammenspiel

Die Idee besteht darin, zuerst einen MIN-HEAP aufzubauen, dessen Wurzel in Position k ist. Dies macht man bottom-up. Zweitens bauen wir einen MAX-HEAP auf, dessen Wurzel in Position k − 1 steht. Jetzt prufen¨ wir fur¨ alle a[i].key im MAX-HEAP, ob a[i].key > ist als die Wurzel des MIN-HEAP. Falls ja, tausche a[i] mit a[k], d.h. rufe swap(i, k) auf. Die Bestimmung der Laufzeit fur¨ dieses Schema ist nicht einfach und wird hier ubergangen.¨

31 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Heapsort und Stabilit¨at

Heapsort sortiert am Ort mit einem Laufzeitverhalten von O(N log N) Schritten im Mittel und im schlechtesten Fall. W¨are das Verfahren jetzt noch stabil, d.h. wurden¨ die S¨atze mit gleichen Schlusseln¨ ihre relative Eingabeordnung behalten, w¨aren alle unsere Wunsche¨ erfullt.¨ Betrachte hierzu die Abbildung 5 mit einer un¨aren Datei bestehend aus sechs S¨atzen. Die Indexzahlen deuten die (unsichtbare) Eingabeordnung an.

32 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Situation auf einer un¨aren Datei

Eingabe: 11, 12, 13, 14, 15, 16 und vor swap(15, 14) 11 16 15

12 13

14 15 16 16 11

11 12 13 14 15 16

16 12 13 14 15 11

15 12 13 14 16 11 . . 12 13 14 15 16 11 Abbildung 5: Heapsort auf einer un¨aren Datei.

33 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Eine zyklische Vertauschung?

Die Eingabeordnung wurde nicht aufrechterhalten, aber das Ergebnis sieht verd¨achtig nach einer zyklischen Vertauschung (shift) aus. Das ist aber nicht allgemein wahr, wie man an einer bin¨aren Datei mit Nullen und Einsen sieht (vgl. Abbildung 6).

34 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Kein Zyklus auf bin¨arer Eingabe

Eingabe: 11, 02, 03, 14, 15, 06 Situation nach Aufbau 11

0214 03

14 02 15 06

11 14 03 02 15 06 Abbildung 6: Heapsort auf einer bin¨aren Datei.

35 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Undurchsichtig aber nicht hoffnungslos?

 Die Turku-Vorlesung beendete 1987 an dieser Stelle die Untersuchung der Stabilit¨at mit der Bemerkung, die Situation sei undurchsichtig, aber nicht hoffnungslos. Allerdings ist auch im Jahr 2014 noch keine stabile Heapsort-Variante gefunden worden.

36 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Deapsort – Duplikatseliminierung mit Heaps

In diesem Abschnitt beschreiben wir einen fiktiven Algorithmus, genannt Deapsort, der w¨ahrend der Turku-Vorlesung vorgeschlagen wurde. Die Idee ist, die Sortierung mit einer Duplikatseliminierung “on-the-fly” zu kombinieren.

In der Heapaufbau- und in der Selektionsphase k¨onnten wir S¨atze (Knoten) aussondern, die Schlusselwerte¨ haben, die identisch sind mit denen auf der Bruder- oder Sohnposition. Der zu entfernende Satz mit einem Duplikat k¨onnte durch das rechteste Blatt (oder linkeste Blatt in einem Min-Heap mit Wurzel ganz rechts) ersetzt werden. Man beachte, dass dieses Blatt dann hoch- oder runtersteigen kann.

37 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte df-Heap

Als Beispiel betrachte man den schlechtesten Fall fur¨ einen Heap mit der Eigenschaft, dass keine zwei Bruderknoten¨ und kein Vater-Sohn-Paar gleiche Schlussel¨ haben. Wir nennen so einen Heap einen duplikatsfreien Heap (df-Heap)2. Die Abbildung 7 ist ein Min-Heap. Die maximalen Werte von N fur¨ n = 1, 2,..., 8 in diesem Beispiel sind 1, 2, 4, 6, 10, 14, 22, 30.

2Wir sprechen vom schlechtesten Fall, weil wir den gr¨oßten df-Heap mit N Knoten suchen, den man mit n unterschiedlichen Schlusseln¨ erzeugen kann. 38 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte df-Heap bildlich

1

2 3

3 4 4 5

4 5 5 6 5 6 6 7

5 6 6 7 6 7 7 8 6 7 7 8 7 8 8 9 Abbildung 7: Ein df-Heap: keine Vater-Sohn- oder Bruder-Knoten¨ haben gleiche Schlussel.¨

39 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Zahlenspiele I

Beobachtung: Ein df-Heap mit n unterschiedlichen Werten hat h¨ochstens N = f (n) = 2n/2+1 − 2 Knoten fur¨ n gerade und N = (f (n − 1) + f (n + 1))/2 Knoten fur¨ n ungerade.

Betrachte hierzu noch ein Beispiel mit N = 10 S¨atzen mit n = 5 unterschiedlichen Werten (Abbildung 8).

40 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Zahlenspiele II

Eingabe: 5 2 3 5 1 1 3 2 4 5 Eingabe als Baumstruktur noch ohne Heap-Eigenschaft

5

4 2

3 1 1 5

3 2 5 m¨ogliche Ausgabe

Duplikate z }| { 3 1 5 2 5 1 2 3 4 5 Abbildung 8: Duplikatseliminierung in einem Min-Heap.

41 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Vorgehensweise

Wenn wir mit einem Min-Heap arbeiten, der die Wurzel rechts hat, sammeln wir Duplikate in der Heap-Aufbauphase links, wie in Abbildung 8 angedeutet. Am Ende dieser Phase 1 kann der df-Heap aber noch weitere Duplikate enthalten.

Daher mussen¨ wir die Sortierung weitertreiben und wiederholt die Wurzel entfernen wie im normalen Heapsort. Die jetzt entdeckten Duplikate mussen¨ irgendwo untergebracht werden, vielleicht als “Rad”. Eine andere Strategie w¨are, in Phase 2 zu einer normalen Sortierung zuruckzukehren,¨ einschließlich der noch in der Folge enthaltenen Duplikate, und diese im Anschluss aus der sortierten Folge herauszuziehen, z.B. wieder mit der Radtechnik.

42 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Raum fur¨ Vorschl¨age

Im oben gezeigten Beispiel aus Abbildung 8 wurden alle Duplikate in Phase 1 entdeckt. Man beachte aber, dass die dort abgebildete Ordnung der Duplikate implementierungsabh¨angig ist und wom¨oglich von keinem Algorithmus reproduziert werden kann.

Wie man an diesen vagen Worten erkennt, wurde das Konzept nie in einen konkreten Algorithmus umgesetzt. Stattdessen entwickelten Teuhola und Wegner sp¨ater einen Duplikats- eliminierungsalgorithmus, der minimalen Platzbedarf und im Mittel lineare Laufzeit bietet. Er h¨ort auf den radikalen Namen DDT und beruht auf Hashing [TW91].

43 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Literatur I

[ASSS86] M. D. Atkinson, J.-R. Sack, N. Santoro, and T. Strothotte, Min-Max Heaps and Generalized Priority Queues, CACM 29 No. 10 (1986), 996–1000. [Flo64] Robert W. Floyd, Algorithm 245: Treesort3, Commun. ACM 7 (1964), no. 12, 701. [Gon84] Gaston H. Gonnet, Handbook of Algorithms and Data Structures, Addison-Wesley, 1984. [Knu73] Donald E. Knuth, The Art of Computer Programming, Volume III: Sorting and Searching, Addison-Wesley, 1973. [Knu98] , The Art of Computer Programming. Vol. 3: Sorting and Searching, 2nd ed., vol. 3, Addison-Wesley, 1998.

44 / 45 Das nie endende Wunder des Heap Floyds Verbesserung Variationen und offene Aspekte Literatur II

[Teu93] Jukka Teuhola, Bottom-up heapsort, 1993, [Online; accessed 17-June-2014]. [TW91] Jukka Teuhola and Lutz Michael Wegner, Minimal space, average linear time duplicate deletion, Commun. ACM 34 (1991), no. 3, 62–73. [Wil64] J.W.J. Williams, Algorithm 232 (Heapsort), CACM 7 (1964), 347–348.

45 / 45 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung

Sortierverfahren Smoothsort

Lutz Wegner

3. Juli 2014

1 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung Inhaltsverzeichnis

1 Ein Heapsort mit Beschleunigung Smoothsort – Dijkstras Idee

2 Erste Phase Leonardo-B¨aume

3 Zweite Phase Rechteste Wurzel entfernen

4 Hertels Ub¨ erarbeitung Obere Schranken bei Vorsortierung Nachbetrachtung

2 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung Dijkstras Idee

Diese Lektion besch¨aftigt sich mit einer Variation des Heapsort, die bei vorsortierten Eingaben Vorteile verspricht. Diese Variation wurde von E.W. Dijkstra und A.J.M van Gasteren [DvG82, Dij82] vorgeschlagen. Der Algorithmus in der zweiten Arbeit wurde von Dijkstra Smoothsort genannt. Stefan Hertel hat dieses Sortierverfahren umgeschrieben und analysiert [Her83].

3 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung Heapsort

Heapsort konstruiert zun¨achst einen Heap mit dem Maximum (Wurzel) ganz links. Danach entfernt der Algorithmus fortlaufend die Wurzel, schmeißt sie nach rechts im Tausch gegen das rechteste Blatt, das dann in den Heap sinkt, wobei die Heapeigenschaft wieder herstellt wird (vgl. Abbildung 1). Damit – und auch wegen der “ebenenweisen” Speicherung der Knoten – kann Heapsort keinen Nutzen aus langen Folgen aufsteigender Schlussel¨ ziehen.

4 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung Grundprinzip

max

unsorted prefix sorted suffix

Abbildung 1: Grundkonstruktion fur¨ Heapsort und Varianten

5 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung Smoothsort

Smoothsort beh¨alt auch das Vorgehen in zwei Phasen, aber statt einem Heap werden Folgen von Heaps konstruiert. Jeder dieser B¨aume hat die Heapeigenschaft. Die Gr¨oße der B¨aume f¨allt von links nach rechts, d.h. ganz links steht ein Heap maximaler Gr¨oße, danach kleinere, so dass insgesamt alle N Knoten aufgeteilt sind. Zus¨atzlich wird dafur¨ gesorgt, dass die Wurzeln dieser B¨aume eine aufsteigende Folge mit dem Maximum rechts bilden.

In der zweiten Phase steht rechts immer das Maximum der verbleibenden Schlussel¨ bereits an der richtigen Position und muss nicht bewegt werden. Der Knoten wird nur “logisch” vom Baum entfernt, wodurch zwei Teilb¨aume entstehen, die Teil des “Walds” werden. Durch lokale Vertauschungen wird dafur¨ gesorgt, dass die Wurzeln der Heaps im “Wald” wieder eine aufsteigende Folge ergeben.

6 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung Organisationsfragen

Damit die Wurzel jedes einzelnen Heaps (das Maximum) jeweils rechts steht, werden die Knoten der Heaps jetzt nicht mehr ebenenweise gespeichert, sondern in postorder.

Fur¨ die Baumgr¨oßen verwendet Dijkstra ein rekursives Bildungsgesetz, das die sch¨one Eigenschaft hat, dass ein Heap gultiger¨ Gr¨oße mit dem Entfernen der Wurzel in zwei Teilb¨aume zerf¨allt, die beide automatisch wieder gultige¨ Gr¨oßen haben. Die Folge der Leonardo-Zahlen erfullt¨ diese Eigenschaft.

Drittens muss man festhalten, welche B¨aume existieren. Diese Buchhaltung ubernimmt¨ ein Bitvektor p. Mehr dazu unten.

7 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung Leonardo-Zahlen und Leonardo-B¨aume

Wir bauen einen Wald von B¨aumen, dessen Gr¨oße von den Leonardo-Zahlen1 bestimmt wird.

Ln = Ln−1 + Ln−2 + 1

... 41 25 15 9 5 3 1 1 (−1) Die Wurzeln der B¨aume werden in nicht-absteigender Ordnung (aufsteigend oder gleich) angeordnet. Die B¨aume selbst werden in postorder gespeichert, d.h. die S¨ohne stehen links vom Vater. Im Gegensatz dazu speichern Heaps in Heapsort ihre Knoten ebenenweise.

1 Eng verwandt mit den Fibonacci-Zahlen Fn = Fn−1 + Fn−2. 8 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung Leonardo-B¨aume – der etwas andere Wald

Man beachte auch, dass in einem Leonardo-Baum ein Knoten entweder zwei S¨ohne hat oder keinen. Die Anordnung der B¨aume ist so, dass der gr¨oßere Baum links steht (vgl. Abbildung 2).

LTi+2

LTi+1 LTi

LTi LTi−1 ......

...... Abbildung 2: Ordnung der Leonardo-B¨aume

9 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung Die Leonardo-Repr¨asentation

Jetzt schauen wir uns eine geeignete Repr¨asentation der Leonardo-Zahlen an, die festh¨alt, welche B¨aume vorliegen. Betrachte hierzu das Triple

(p, b, c)

mit p ein Bitstring, der aussagt, welche B¨aume da sind; ein Bitwert ’1’ repr¨asentiert eine vorliegende Gr¨oße; alle rechten Nullen werden entfernt2. b die Gr¨oße des kleinsten existierenden Leonardo-Baums (gibt die Anzahl der entfernten Nullen an)

c die zu b kleinere Leonardo-Zahl, d.h. wenn b = Li , dann ist c = Li−1. 2Bei einer Implementierung sollte man p als 64-Bit-Integer vereinbaren, da p sonst schnell uberl¨ ¨auft. Die 31. Leonardo-Zahl ist “nur” 4356617. 10 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung Beispiel zur Leonardo-Repr¨asentation

Beispiel Die Daten liegen in dem Array A[0 ... 12], d.h. A hat Gr¨oße 13. Die Leonardo-Faktorisierung ist 9, 3, 1.

0 −−−−−−−−−−−−−−−−−−−→ p = 10110 entferne rechteste Nullen p = 10112

= 1110 (p, b, c) = (11, 1, 1)

Wir beobachten, dass es in dieser Repr¨asentation nie zwei aufeinanderfolgende Einsen gibt – mit Ausnahme der rechtesten zwei Bits.

11 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung N¨achste Leonardo-Zahl berechnen

Als N¨achstes pr¨asentieren die Autoren Prozeduren Up, Up1, Down, Down1, um die n¨achstgr¨oßere (kleinere) Leonardo-Zahl aus den globalen Variablen b, c, b1, c1 zu berechnen (siehe Listing 1).

12 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung Up, Down, Up1, Down1

Listing 1: Berechnung der Leonardo-Zahlen. procedure Up ; var aux : in teg er ; begin aux := b+c+ 1; { next bigger L−N} c := b; b := aux end ; {Up1 the same with b1, c1 }

procedure Down ; var aux : in teg er ; begin aux := b − c − 1 ; { next smaller L−N} b := c; c := aux end ; {Down1 the same with b1, c1 }

13 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung Wie Dijkstra sift erkl¨art

Der “magische” Teil ist die neue sift-Prozedur aus dem Listing 2. Dijkstra erkl¨art sie so in der Arbeit [Dij82, p. 228]: - sift angewandt auf ein Element ohne gr¨oßeren Sohn ist ein skip,

- sift angewandt auf ein Element M[r1], das einen gr¨oßeren (maximalen) Sohn in M[r2] hat, fuhrt¨ zu einem swap(M[r1], M[r2]), gefolgt von einem sift fur¨ M[r2]. Als Beispiel betrachte man Abbildung 3, hier mit sift fur¨ den Schlussel¨ 8 an der Wurzel. Abbildung 4 zeigt das Ergebnis danach.

14 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung sift des Knotens mit Schlussel¨ 8

8 15

15 14 12

13 14 9 7 11

10 6 9 8 2 5 3

4 1

Abbildung 3: Sift der 8 in den Heap, der als Leonardo-Baum geordnet ist.

15 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung Einfugen¨ der 8 mittels sift

z }| { z }| { z }| { z }| {z }| { z }| {z}|{ z }| {z}|{ 4 1 10 6 13 8 2 9 14 5 3 7 11 12 15

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

Abbildung 4: Array-Speicherung mit Schlussel¨ 8 in einer Blattposition.

16 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung

Listing 2: Prozedur sift fur¨ Heaps. procedure s i f t ; { r1 i s r o o t } var r2 : in teg er ; begin while b1 >= 3 do begin r2 := r1 − b1 + c1 ; i f M[ r2 ] < M[ r1 − 1 ] then begin r2 := r1 − 1 ; Down1 end ; { largest son in r2 } i f M[ r1 ] ≥ M[ r2 ] then b1 := 1 e l s e begin swap(M[r1], M[r2]); r1 := r2; Down1 end ; end { w h i l e } end { s i f t } ;

17 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung Die Bedeutung von r1, r2, c1, b1

r1-1 r2 r1 c1

b1 | {z } zu konstruierender Baum Abbildung 5: Die Bedeutung der Variablen in der Prozedur sift.

18 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung Beispiel

Als Beispiel betrachte man die Eingabefolge aus Abbildung 6.

4 5 2 1 3 7 11 9 6 12 13 8 10

0 1 2 3 4 5 6 7 8 9 10 11 12

Abbildung 6: Eingabe fur¨ Phase 1 – ursprungliche¨ Anordnung im Array.

19 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung Baumaufbau I

Fur¨ N = 13 Schlussel¨ ist die Leonardo-Faktorisierung (9, 3, 1). Die generierten B¨aume in den ersten neun Schritten sieht man in Abbildung 7.

20 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung Baumaufbau II

5 5 1

4 4 5 4 2 4 2 | {z } | {z } | {z } | {z } q=1 q=2 q=3 q=4

5 11

4 1 5 9

3 2 4 1 7 6

3 2 | {z } | {z } q=5 q=9 Abbildung 7: Aufbau des Leonardo-Baums bis q = 9.

21 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung Die Routine trinkle

Jetzt passt der n¨achstgr¨oßere Leonardo-Baum nicht mehr in ein Array fur¨ N = 13. Daher gibt es eine Prozedur trinkle, die den Wald wiederherstellt, wie in Abbildung 8 gezeigt.

11 ≤ 13 > 10

5 9 12 8

4 1 7 6

3 2

Abbildung 8: Situation beim Aufruf von trinkle fur¨ den gegebenen Wald.

22 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung Wurzelbehandlung

Die Regel fur¨ den Tausch der Wurzeln ist wie folgt. Tausche die Wurzel des gegenw¨artigen Baums mit der Wurzel des Baums links davon genau dann, wenn die Wurzel links gr¨oßer ist als die des gegenw¨artigen Baums und gr¨oßer als beide S¨ohne der gegenw¨artigen Wurzel (so die S¨ohne existieren). Sonst lasse die neue Wurzel in den gegenw¨artigen Baum einsinken. Gab es einen Wurzeltausch, dann untersuche weitere Austauschnotwendigkeiten links.

Im Beispiel oben (vgl. Abbildung 8) hatten wir 13 > 10, und es gab keine S¨ohne fur¨ den Einzelknoten 10. Daher tauschen wir die 13 mit der 10. Dies fuhrt¨ zu der Situation in Abbildung 9.

23 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung Tausch der Wurzeln der B¨aume bildlich

11 > 10 ≤ 13

5 9 12 8

Abbildung 9: Nach dem Austausch der Wurzeln der rechtesten B¨aume.

24 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung Phase 1 gegen Ende

Jetzt haben wir 11 > 10, aber 11 ist nicht gr¨oßer als beide S¨ohne von 10, diese sind 12 und 8. Daher lassen wir die 10 in den Leonardo-Baum der Gr¨oße 3 absinken, was die Endsituation aus Abbildung 10 ergibt. Damit endet die Erl¨auterung der Baumaufbauphase.

11 ≤ 12 ≤ 13

5 9 10 8

Abbildung 10: Situation zum Ende der Phase 1.

25 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung Zweite Phase – rechteste Wurzel entfernen

In der zweiten Phase entfernen wir kontinuierlich die rechteste Wurzel (das Maximum). Eine Variable q l¨auft von N bis 1 und kontrolliert den Ablauf. Wenn die Wurzel zwei S¨ohne hat, verwende eine Prozedur semitrinkle, die sich um die beiden Teilb¨aume kummert,¨ vertausche deren Wurzeln, falls n¨otig, und verwende trinkle (siehe Listing 3), um den “Wald” (engl. root-sorted forest) wiederherzustellen.

26 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung Prozedur trinkle I

Listing 3: Prozedur trinkle fur¨ Heaps. while q <> 0 do begin { look at next node } q := q − 1 ; i f b = 1 {a tree of size 1} then begin r := r − 1 ; {new r o o t } p := p − 1 ; { delete tree of size 1} while ( p mod 2 = 0) and ( p > 0) do begin p := p div 2 ; Up end end { get rightmost LT} e l s e begin

27 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung Prozedur trinkle II

p := p − 1 ; r := r − b + c ; {on left subtree } i f p > 0 then semitrinkle; Down ; p := p ∗ 2 + 1 ; { insert new tree } r := r + c ; semitrinkle; Down ; p := p ∗ 2 + 1 { insert new tree } end end ;

28 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung Baumschnitt

Schauen wir uns die Regeln fur¨ das Entfernen der Wurzel des ersten Heaps in dem wurzelsortierten “Wald” an. Abbildung 11 zeigt die generelle Situation. Ein Pfeil von Knoten x nach y deutet an, dass x ≤ y. Im Moment soll Knoten A entfernt werden.

D A D ≤ B? E F B B ≤ C? C

| {z } zwei neue B¨aume TL und TR Abbildung 11: Entfernen Knoten A.

29 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung Trinkle, semitrinkle, swap

Der Algorithmus vergleicht zuerst D mit B mittels semitrinkle. Wenn D > B, dann swap (D, B), was die Heapeigenschaft fur¨ TL erh¨alt, und trinkle B in den wurzelsortierten “Wald”. Danach, falls root(TL) > C, rufe swap(C, root(TL)) und trinkle fur¨ C auf.

30 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung Beispiel (Forts.)

Betrachten wir nochmals unser Beispiel. Jetzt soll Knoten A = 12 entfernt werden (Abbildung 12).

3 2 4 1 5 7 6 9 11 10 8 12 13

11 12 11 > 10! 5 9 10 8

Abbildung 12: Entfernen Knoten A = 12.

31 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung Beispiel (Forts.)

Da D nicht ≤ B ist, brauchen wir ein swap(11, 10) und trinkle fur¨ 10, was aber nichts macht. Jetzt ist 11 nicht ≤ 8, wir brauchen noch ein swap und trinkle fur¨ 8, was wieder nichts bewirkt, da 8 ein Blattknoten ist.

3 2 4 1 5 7 6 9 10 11 8 12 13

10 12

5 9 11 8 11 > 8!

Abbildung 13: Entfernen Knoten A = 12 und swap(11,10).

32 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung Vertauschung der Wurzeln

Dies fuhrt¨ zu einer Situation, bei der die Wurzel des linken Baums 10 ist, was gr¨oßer ist als 8. Daher gibt es einen weiteren Aufruf swap(10,8) und 8 sinkt in den Heap, was die 9 an die Wurzel bringt (Abbildung 14).

10 8 9 12 13

5 9 8 8 11 10 4 1 7 6

3 2

Abbildung 14: Nach swap(10,8) und trinkle fur¨ Wert 8.

33 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung Das Ende der Phase 2

Danach 11, 10, 9 und 8 zu entfernen geht leicht und verlangt keine swaps oder Aufrufe von trinkle. Nach dem Entfernen der 8 haben wir drei “B¨aume”, 5, 7 und 6. Hier ist 5 ≤ 7, aber 7 > 6, was zu swap(7,6) und trinkle fur¨ 6 fuhrt.¨ Die H¨orer sollten sich die Situation aufmalen und die folgenden Schritte weiterverfolgen, darunter ein swap(4,1) und trinkle fur¨ 1, was eine sift-Operation ist. Damit schließen wir die Beschreibung der Phase 2.

34 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung Hertels Ub¨ erarbeitung

Hertel [Her83] schrieb Smoothsort um unter Verwendung vollst¨andiger bin¨arer B¨aume. Er zeigt, dass die erste Phase eine Komplexit¨at von O(n) hat, dass Smoothsort aber nicht Mehlhorns [Meh79, Meh84] obere Schranke

O(n(1 + log(F /n)))

fur¨ vorsortierte Eingabe unterschreitet, wobei F die Anzahl der Pn Vertauschungen ist. Pr¨aziser gesagt, F = i=1 fi mit fi = |{xj ; j > i and xj < xi }|. F ist also ein Maß der Vorsortiertheit.3 Vielmehr braucht Smoothsort zum Sortieren einer Permutation mit O(n log n) Vertauschungen Θ(n log n) Swap-Aufrufe.

3Eine vollst¨andig sortierte Datei hat F = 0, eine v¨ollig unsortierte hat F ≈ n2. 35 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung Nachbetrachtung

Smoothsort gilt nicht als sonderlich schnelles Verfahren.4 Nimmt man den Originalalgorithmus, von dem Dijkstra sagt, dass er darin auf alle Optimierungen verzichtet habe, dann ergibt ein Testlauf mit N = 10 Mio. paarweise verschiedenen Schlusseln¨ rund 575 Mio. Schlusselvergleiche¨ und eine Laufzeit von ca. 15,2 s. Zum Vergleich: Heapsort ohne Floydverbesserung bringt es auf ≈ 434 Mio. Schlusselvergleiche¨ und 5,6 s Laufzeit in unserer Testumgebung.

Selbst bei einer bin¨aren Datei (N = 10 Mio., M = 5 Mio.) ben¨otigt Smoothsort 229 Mio. Schlusselvergleiche¨ und rund 6,1 s, was man kaum als “smooth” bezeichnen kann.

4Vgl. hierzu auch den interessanten Blog http://calmerthanyouare.org/2013/05/31/qsort-shootout.html 36 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung Literatur I

[Dij82] Edsger W. Dijkstra, Smoothsort, an alternative for sorting in situ, Sci. Comput. Program. 1 (1982), no. 3, 223–233. [DvG82] E.W. Dijkstra and A.J.M. van Gasteren, An introduction to three algorithms for sorting in situ, IPL 15 3 (1982), 129–134. [Her83] Stefan Hertel, Smoothsort‘s behaviou an presorted sequences, IPL 16 (1983), 165–170. [Meh79] Kurt Mehlhorn, Sorting presorted files, Theoretical Computer Science (Klaus Weihrauch, ed.), Lecture Notes in Computer Science, vol. 67, Springer, 1979, pp. 199–212.

37 / 38 Ein Heapsort mit Beschleunigung Erste Phase Zweite Phase Hertels Ub¨ erarbeitung Literatur II

[Meh84] , Data structures and algorithms 1: Sorting and searching, Monographs in Theoretical Computer Science. An EATCS Series, vol. 1, Springer, 1984.

38 / 38 Sortieren komplexer Objekte Hillsort Nachtrag

Sortierverfahren Hillsort – ein externer Heapsort

Lutz Wegner

10. Juli 2014

1 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Inhaltsverzeichnis

1 Sortieren komplexer Objekte NF2-Tabellen Anforderungen Heapsort im VS

2 Hillsort Ein Heap von Seiten Analyse Ein Heap mit L¨ochern Analyse

3 Nachtrag Was Katajainen sagt

2 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Tabellen in geschachtelter Form

Betrachten wir sog. NF 2-Tabellen (Non-First-Normal-Form-, geschachtelte Tabellen) mit relationswertigen Attributen, Listen, Multimengen usw. (vgl. Tabelle 1).

Tabelle 1: Geschachtelte Tabelle mit Publikationen

{REPORTS} TITLE {DESCRIPTION} NAME KEYWORD WEIGHT Dadam Time Versions in NF 2-Database Systems Visited Databases 30 Time Versions 50 Teuhola NF 2 20 Dadam Time Versions in NF 2-Database Systems Revisited Time Versions 30 Databases 50 Teuhola NF 2 20 Wegner A Stackless Quicksort Sorting 50 Analysis 50 Teuhola The External Heapsort Sorting 25 Heapsort 25 NF 2 20 Wegner Analysis 30

3 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Duplikatsentdeckung ub¨ er Sortieren?

Wie wurde¨ in einem solchen Datenmodell Duplikatsentdeckung funktionieren? Wenn man die Aufgabe mittels Sortierung l¨ost, mussen¨ wir eine Ordnungsrelation “<” fur¨ das Datenmodell definieren.

Sei “<” definiert fur¨ atomare Objekts, also fur¨ Integer, Boolean, Zeichen (char), Text, Gleitkommazahlen (real), ... in der ublichen¨ Form, d. h. wir verwenden eine numerische bzw. lexikographische Ordnung. Fur¨ komplexe Objekt gibt es verschiedene Alternativen. Wir haben hier eine Definition gew¨ahlt, die auf einem rekursiv ermittelten Minimum beruht.

4 / 43 Sortieren komplexer Objekte Hillsort Nachtrag

Definition Fur¨ Objekte A und B desselben Typs definiere A < B ⇐⇒ 1) FIRST (A) < FIRST (B) oder 2) FIRST (A) = FIRST (B) und A \ FIRST (A) < B \ FIRST (B) oder 3) A leer und B nicht leer, wobei a) FIRST ({}), FIRST (<>), FIRST ([ ]) undefiniert sind

b) fur¨ Mengen FIRST ({l1,..., ln}) = li mit li < lj ∀ i 6= j

c) fur¨ Listen FIRST (< l1, l2,..., ln >) = l1

d) fur¨ Tupel FIRST ([m1 : l1,..., mn : ln]) = li mit mi < mj ∀ i 6= j und mi < mj bezieht sich auf eine vordefinierte Ordnung der Spalten, etwa uber¨ Attributnamen, und x \ FIRST (x) bezeichnet das Objekt x ohne FIRST (x).

5 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Beispiel mit flacher Tabelle

Ubung¨ Man prufe¨ die Definition auf einer (flachen) Tabelle (Relation) mit atomaren Attributen.

{PERSON} NAME AGE SMITH 40 JONES 40 SMITH 30 JONES 40

6 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Beispiel mit geschachtelter Tabelle

Ubung¨ Hier jetzt ein Relation mit relationswertigem Attribut.

{PERSON} NAME AGE {CHILD} NAME AGE SMITH 40 ANNE 18 MIKE 16 JONES 40 ANNE 19 JUDIE 23 SMITH 30 { } JONES 40 ANNE 19 JUDIE 23 ANNE 19

7 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Sortierverfahren fur¨ komplexe Objekte I

Ein Verfahren, das unsere Ordnungsrelation unterstutzt,¨ musste¨ 1.) das Minimum in O(N) Schritten liefern, 2.) den n¨achsten Schlussel¨ in aufsteigender Ordnung in O(log N) Schritten liefern, 3.) dazwischen sich “einfrieren” lassen, 4.) auf externen Dateien arbeiten. Die ersten zwei Eigenschaften ließen sich als “Sortieren in Echtzeit” oder “Online-Sortieren” bezeichnen. Die nachfolgende Tabelle 2 vergleicht die Konkurrenten.

8 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Sortierverfahren fur¨ komplexe Objekte II

Tabelle 2: Kandidaten fur¨ Sortieren in Echtzeit

Methode min. Schlussel¨ in O(N) n¨achster in O(log N) √ Selection/Insert − √ Bubble − Merge − (−) Radix − (−) Shell − (−) √ √ Quicksort ( ) ( ) √ √ Heapsort

9 / 43 Sortieren komplexer Objekte Hillsort Nachtrag And the winner is ...

Offensichtlich ist Heapsort der am besten passende Kandidat. Heapsort wurde von J. W. J. Williams 1964 [Wil64] erfunden und ist verwandt mit einem fruher¨ entdeckten Verfahren namens Treesort, das auf Robert W. Floyd zuruckgeht¨ [Flo62]. Aber funktioniert es auch fur¨ externe Dateien?

10 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Heapsort im virtuellen Speicher I

Timo O. Alanka, Hannu H. A. Erki¨o, und Ilkha J. Haikala [TAH84] haben das Verhalten verschiedener Sortieralgorithmen im virtuellen Speicher untersucht. Abbildung 1 zeigt einen Heap in einem in Seiten aufgeteilten Speicher. Die Seiten wurden ebenenweise gefullt,¨ wie fur¨ Heaps ublich.¨

11 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Heapsort im virtuellen Speicher II

Abbildung 1: Ein Heap mit vier Knoten je Seite.

12 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Ub¨ erschlagsrechnung

Fur¨ N S¨atze verteilt auf m Seiten ben¨otigt jeder heapify-Schritt log2 m Seitenzugriffe. Das bedeutet O(N log2 m) Seitenzugriffe insgesamt. Eine kleine Uberschlagsrechnung¨ (back-of-the-envelope calculation) l¨asst nichts Gutes erwarten. Beispiel Gegeben sei eine 4 MB Relation, 40 Bytes je Tupel, die klassische 4 KB Seite, eine langsame 18 ms Platte. Die Gesamtlaufzeit w¨are dann 100.000 log2(1000) · 18/1000[s] = 5[h].

Unser Ziel ist aber eine m log2 m Methode, die obige Relation in 3 Minuten1 sortiert!

1Zeit nach obigen Modellannahmen, intern heute eher < 1 Sekunde. 13 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Hillsort – ein externer Heapsort

Eine L¨osung fur¨ einen externen Heapsort wurde von Teuhola und Wegner entwickelt und 1989 als Hillsort [WT89] ver¨offentlicht. Die Grundidee ist wie folgt. - Betrachte einen Heap von Seiten. - Ordne die S¨atze in den Seiten aufsteigend an. - Benutze eine neue Invariante fur¨ die Ordnung der Seiten (siehe Abb. 2). - Ersetze Schlusselvergleiche¨ durch Seitenverschmelzungen (page merges).

14 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Invariante der Seitenordnung

a min(a) > max(b) min(a) > max(c)

b c

Abbildung 2: Invariante fur¨ Heap von Seiten.

Diese Ordnung von a, b und c kann mit zwei Merge-Operationen der beteiligten Seiten hergestellt werden (siehe Listing 1).

15 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Seitenordnung herstellen I

Listing 1: Aufrechterhaltung der Heap-Invariante bei Hillsort. if min(b) < min(c) then begin merge pages(b, c); highson := c {the upper half is in c} end else begin merge pages(c, b); highson := b {the upper half is in b} end; merge pages(highson, a) {the upper half is in a}

16 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Implementierung

Im eigentlichen Pascal-Programm heißt diese Routine merge pages(f, i, j), wobei f eine Datei (Array) von Seiten ist und die Parameter i und j Indizes in das Array von Seiten sind. Die Prozedur swap pages(f, i, j) macht das Offensichtliche, d.h. sie tauscht die beiden Seiten i und j in f . Schließlich stellt heapify(f, i, r) die Heap-Eigenschaft wieder her, so dass Seite i die gr¨oßten S¨atze in der Datei enth¨alt. Innen verwendet es dazu das gerade besprochene merge pages().

Eine erste Ubersicht¨ zu Hillsort in Anlehnung an den klassischen Heapsort zeigt das Listing 2.

17 / 43 Sortieren komplexer Objekte Hillsort Nachtrag

Listing 2: Erster Uberblick¨ zu Hillsort. procedure Hillsort(var f: paged file; m: page no); var i: page no; procedure sort page(var f: paged file; i: page no); ... procedure swap pages(var f: paged file; i, j: page no); ... procedure heapify(var f: paged file; i, r: page no); ... begin {body of Hillsort} for i := 1 to m do sort page (f, i); for i := m div 2 downto 1 do heapify (f, i, m); for i := m downto 2 do begin swap pages(f, 1, i); heapify(f, 1, i−1) end end {of Hillsort};

18 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Wie sieht es mit der Floyd-Verbesserung aus?

Wir schauen uns jetzt die Prozedur heapify(f, i, r) an. Falls sich ein H¨orer noch an eine Verbesserung des Heapsort durch Robert W. Floyd erinnert, der ein “Loch” in den Heap sinken l¨asst [Flo64], mussen¨ wir leider sagen, dass diese Idee nicht fur¨ einen Heap von Seiten funktioniert. Es gibt aber einen ¨ahnlich schlauen Trick, der sich in dem zitierten Artikel [WT89] findet, den wir ab Folie 33 beschreiben.

19 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Heapify - Herstellung der Heap-Eigenschaft I

Listing 3: Prozedur heapify angepasst an einen Heap von Seiten. procedure heapify (var f: paged file; i, r: page no); var k: page no; stop: boolean;

function min(i: page no): keytype; begin min := f[i, 1].key end;

function max(i: page no): keytype; begin max := f[i, pagesize].key end;

procedure merge pages(var f: paged file; i, j: page no); var aux: page type;

20 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Heapify - Herstellung der Heap-Eigenschaft II

procedure merge(var i, j, k: sequence; length: integer); ... {an ordinary mergesort with auxiliary space} ...

begin {merge pages} merge(f[i], f[j], aux, pagesize) end; {merge pages}

begin {body of heapify} while 2∗i <= r do begin j := 2 ∗ i; k := j; stop := false; if j < r {i has right son}

21 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Heapify - Herstellung der Heap-Eigenschaft III

then begin if min(j) < min(j+1) {lower half to j} then k := j + 1 else j := j + 1; if min(i) >= min(k) {will heapifying end?} then stop := true; if max(j) > min(k) {are sons disjoint?} then merge pages(f, j, k) {larger half to k} end; if min(i) < max(k) {are father and son disjoint?} then begin merge pages(f, k, i); if stop then i := r else i := k

22 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Heapify - Herstellung der Heap-Eigenschaft IV

end else i := r {heapifying ends} end {while} end; {heapify}

23 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Hillsort – die Feinheiten I

Die Endversion von Hillsort hat einige subtile Verbesserungen, z.B. eine zus¨atzliche Abbildung von echten auf virtuelle Seiten, um physisches Umkopieren zu verhindern. Die anf¨angliche Sortierung der Seiteninhalte erledigt man mit einem internen Heapsort, das Verschmelzen der Seiten mit einem gew¨ohnlichen internen Mergesort. Diese Details wurden im Listing 4 weggelassen.

24 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Hillsort – die Feinheiten II

Listing 4: Der vollst¨andige Hillsort mit indirekter Seitenadressierung. procedure Hillsort(var f: paged file; var p: page table; m: page no; pagesize: index in page); var i, aux: page no;

procedure sort page(var f: paged file; i: page no);

procedure heapsort(var a: sequence; r: index); ... {use any suitable internal sort} ...

begin {sort page} heapsort(f[p[i]], pagesize) end; {sort page}

25 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Hillsort – die Feinheiten III

procedure swap pages(i, j: page no); var aux: page no; begin aux := p[i]; p[i] := p[j]; p[j] := aux end;

procedure merge pages(var f: paged file; i, j: page no); var aux: page type;

procedure merge(i, j, k: sequence; length: integer); ... {use any suitable } ...

begin {merge pages} merge(f[p[i]], f[p[j]], aux, pagesize); end; {merge pages}

function min(i: page no): keytype;

26 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Hillsort – die Feinheiten IV

begin min := f[p[i],1].key end;

function max(i: page no): keytype; begin max := f[p[i], pagesize].key end;

procedure heapify(var f: paged file; i, r: page no); ... {see Listing 3 } ...

begin {body of Hillsort} for i := 1 to m do sort page(f, i); aux := p[m]; for i := m downto 2 do p[i] := p[i−1]; p[1] := aux; {root = physically the last page} for i := m div 2 downto 1 do heapify(f, i, m); {build the heap}

27 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Hillsort – die Feinheiten V

for i := m downto 2 do begin {swap the root and i’th page logically} swap pages(1, i); heapify(f, 1, i−1) end end; {Hillsort}

28 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Eine kleine Analyse schadet nie

Die Anzahl der Seitenzugriffe je heapify-Schritt ist

2 · (Pfadl¨ange + 1) = #merges + #swaps + 2.

Die Gesamtzahl der Seitenzugriffe ist dann

m ≤ 2 X (blog ic + 1) [Knu98, p. 154f] i=2 ≈ 2mblog mc + m + 3, 5 m fur¨ die erste Phase des Heap-Aufbaus.

In der Summe ist die Anzahl der Ordnungsoperationen ≤ 2mblog mc + m. Das passt gut zu dem beobachteten Wert fur¨ Seitengr¨oßen > 2, der in der Arbeit [WT89] mit 2m log2 m − 2, 925m angegeben wird.

29 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Puffergr¨oßen

Was die Puffergr¨oße anbetrifft, so verbessert jeder Puffer mit mehr als vier Seiten die Leistung. Die Zahl 4 leitet sich aus der Tatsache ab, dass wir eine “Vaterseite” und zwei “Sohnseiten” im Hauptspeicher halten und eine weitere Seite zum Mischen brauchen. Wenn wir den Puffer uber¨ vier Seiten hinaus vergr¨oßern, etwa auf k extra Seiten, k¨onnen wir log(k + 2) − 1 obere Ebenen des Heap im Speicher halten und sparen uns O(m log k) Zugriffe. Das liefert eine Beschleunigung von O(m log m) auf dann O(m log(m/k)).

30 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Effekt der Seitengr¨oßen

Abbildung 3 zeigt die Zusammensetzung der Ordnungsoperationen in Abh¨angigkeit der Seitengr¨oße (gemessen in S¨atze je Seite). Der Spezialfall einer Seite mit einem Satz verwandelt Hillsort zuruck¨ in den Heapsort ohne merging. Mit wachsender Seitengr¨oße verschwinden die Auswirkungen zuf¨alliger Anordnungen. In other words, once the heap has been built it has a very regular structure where brothers are not disjoint and keys on level i tend to be larger than keys on level i + 1. As a result, a page sinking down practically never stops before it reaches the bottom (Knuth’s value A = 0.349N [Knu73, p. 149], here 0.344m for s = 1, becomes 0 for s > 10). Similarly, the number of father-son merges is surprisingly low. Since we heapify 1.5m times and since the largest number of father-son merges we measured was 1.425m, each page comes to a halt with less than one merge on the average [WT89, p. 924]. 31 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Operationen in Abh¨angigkeit der Seitengr¨oße

·104 sons less than father father-son swaps 1.5 father-son merges brother swaps brother merges 1 der Operationen 0.5 Anzahl

0 100 100.3 100.7 101 101.3 101.7 102 Seitengr¨oße

Abbildung 3: Operationen in Hillsort fur¨ N = 1000. 32 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Ein Heap mit L¨ochern

Wie oben erw¨ahnt, schlug Floyd vor, ein “Loch” in den Heap absinken zu lassen, um damit Vater-Sohn-Vergleiche zu sparen [Flo64]. Auf dem Pfad nach unten werden dann nur noch Sohn-Sohn-Vergleiche ben¨otigt. Wenn das Loch am unteren Rand (Blattebene) angekommen ist, l¨asst man den neuen Satz aufsteigen, bis er seine Endposition erreicht hat. Weil man kleine Schlussel¨ einfugt,¨ ist das nicht sehr hoch. Wie in Vorlesung 7 berichtet, sind nach Knuth die Wahrscheinlichkeiten fur¨ die Ebenen (0, 1, 2 von unten) gerade (0,848, 0,135, 0,016).

In Hillsort beobachten wir den gleichen Effekt, d.h. fast alle Vater-Sohn-Vergleiche fuhren¨ zu einem swap statt einem merge. Allerdings kostet ein swap bei virtueller Adressierung zwar nichts, die wahren Kosten entstehen aber mit dem Laden der zwei Bruderseiten¨ je Ebene. Diese Kosten bleiben gleich, egal ob wir ein Loch oder eine echte Seite herabsinken lassen [WT89, p. 921].

33 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Ein Heap mit permanenten L¨ochern

Somit war eine ganz neue Idee gefragt und Teuhola schlug vor, einen Heap konstanter Gr¨oße mit einer wachsenden Zahl von L¨ochern zu konstruieren. Dies gleicht einem , bei dem fortlaufend das Minimum entfernt wird und ein Loch eingefugt¨ wird, bis nur noch L¨ocher vorhanden sind. Dieser verbesserte Hillsort braucht dafur¨ eine weitere Tabelle mit zwei Bits je Seite. Das reicht zur Unterscheidung zwischen echten Seiten, weißen L¨ochern (haben nie ein weißes Loch als Bruder), schwarzen L¨ochern (sind die Wurzel eines leeren Heap).

34 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Beispiel – Heap mit L¨ochern

Der Prozess des Entfernens des Maximums ist sehr ¨ahnlich wie fur¨ heapify in Heapsort und wird im Detail in [WT89] beschrieben. Die Abbildungen 4 und 5 deuten den Vorgang fur¨ die ersten funf¨ S¨atze in einem Heap mit L¨ochern, der ursprunglich¨ zehn S¨atze enthielt, an.

35 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Heap mit L¨ochern (bildlich)

100 90 70 60 80 50 40 30 10 20 (a) Originaler Heap

70 60 50 40 30 10 20 (b) Nach Entfernen von 100, 90, 80

Abbildung 4: Entfernen der ersten funf¨ S¨atze (Teil 1).

36 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Heap mit L¨ochern (Forts. des Beispiels)

60 20 50 40 30 10 (c) Nach Entfernen von 70

50 20 40 30 10 (d) Nach Entfernen von 60

Abbildung 5: Entfernen der ersten funf¨ S¨atze (Teil 2).

37 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Zusammensetzung des Heap

Abbildung 6 zeigt die Zusammensetzung des Heap w¨ahrend der Auslesephase im modifizierten Hillsort, angefangen mit nur echten Seiten, bis zum Ende mit nur schwarzen L¨ochern.

38 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Zusammensetzung des Heap (Abbildung)

1000

800

600 der Seiten 400 White holes

Anzahl Black holes 200 Real pages

0 0 200 400 600 800 1000 Anzahl der heapify-Schritte

Abbildung 6: Verh¨altnis der L¨ocher im modifizierten Hillsort.

39 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Ersparnis und Laufzeitverhalten

Auch wenn die Pfadl¨ange in diesem Heap mit L¨ochern fest bei log m bleibt, verglichen mit der schrumpfenden L¨ange bei gew¨ohnlichen Heaps, spart man viel: es gelingt, die Anzahl der Seitenoperationen in dieser Phase auf die H¨alfte zu senken. Der Grund liegt in der Tatsache, dass in einem vollst¨andigen Bin¨arbaum die mittlere Pfadl¨ange von der maximalen nur um 1 abweicht! Andererseits, wenn wir eine Seite hochsteigen lassen, laden wir nur eine Seite je Ebene (die hochsteigende Seite bleibt im RAM). Tats¨achlich zeigt die empirische Untersuchung durch eine Simulation in [WT89], dass der modifizierte Hillsort mit L¨ochern die Seitenzugriffe um 40 Prozent und die CPU-Zeiten um etwa 15 Prozent im Vergleich zum unmodifizierten Hillsort verbessert. Bruderseiten¨ in benachbarten Speicherpl¨atzen auf der Platte reduzieren zus¨atzlich die Kopfpositionierungszeit (seek time), ein weiterer Vorteil neben der Tatsache, dass das Verfahren in situ arbeitet. 40 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Nachtrag

 Am 4. Dezember 2013 schrieb Jukka Teuhola: Another surprising news: Jyrki Katajainen, who has done a lot of work with heaps, told me that our External Heapsort is outstanding as an INTERNAL sorting algorithm, due to locality of reference in cache memory. In his words, our algorithm is the only heapsort that has really improved Williams’ original version. Katajainen gave a presentation in Dagstuhl last summer, and a reference to his (edited) material is behind the link http: // www. diku. dk/ hjemmesider/ ansatte/ jyrki/ Myris/ Kat2013-09-23P. html See especially p. 12. Na also, wer sagt es denn ...

41 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Literatur I

[Flo62] Robert W. Floyd, Algorithm 113: Treesort, Commun. ACM 5 (1962), no. 8, 434. [Flo64] , Algorithm 245: Treesort3, Commun. ACM 7 (1964), no. 12, 701. [Knu73] Donald E. Knuth, The Art of Computer Programming, Volume III: Sorting and Searching, Addison-Wesley, 1973. [Knu98] , The Art of Computer Programming. Vol. 3: Sorting and Searching, 2nd ed., vol. 3, Addison-Wesley, 1998. [TAH84] H. H. A. Erkioe T.O. Alanka and I. J. Haikala, Virtual memory behavior of some sorting algorithms, IEEE TSE SE 10 No. 4 (1984), 422–431.

42 / 43 Sortieren komplexer Objekte Hillsort Nachtrag Literatur II

[Wil64] J.W.J. Williams, Algorithm 232 (Heapsort), CACM 7 (1964), 347–348. [WT89] Lutz Michael Wegner and Jukka Teuhola, The external heapsort, IEEE Trans. Software Eng. 15 (1989), no. 7, 917–925.

43 / 43 Nachtrag Ruckblick¨ Ausblick

Sortierverfahren Zusammenfassung, Ruck-¨ und Ausblick

Lutz Wegner

10. Juli 2014

1 / 23 Nachtrag Ruckblick¨ Ausblick Inhaltsverzeichnis

1 Nachtrag Deapsort L¨osung

2 Ruckblick¨ Weglassungen Einsichten

3 Ausblick Zweiwege- versus Dreiwegeaufteilungen

2 / 23 Nachtrag Ruckblick¨ Ausblick Nachtrag Deapsort

Am Ende der Lektion 7 machten wir Betrachtungen zu einer “on-the-fly Duplikatseliminierung” mit einem modifizierten Heapsort, allerdings ohne genaue Angaben. Zun¨achst stellten wir die Definition eines df-heaps vor (“df”: locally duplicate free), bei dem nie zwei Bruder-¨ oder Vater-Sohn-Knoten gleiche Werte haben. Das garantiert naturlich¨ keine globale Duplikatsfreiheit, w¨are aber eine hubsche¨ Eigenschaft.

Die Uberlegung¨ war, eine modifizierte heapify-Methode anzugeben, die ein Blatt an der Wurzel absinken l¨asst und, vorausgesetzt der Heap hatte vorher die lokale df-Eigenschaft, einen Heap abliefert, der wieder diese Eigenschaft hat. Aus diesen Vor- und Nachbedingungen k¨onnte man dann Absch¨atzungen ableiten.

3 / 23 Nachtrag Ruckblick¨ Ausblick Nachteile der ursprunglichen¨ Idee

Tats¨achlich ist diese Idee schwierig umzusetzen. Erstens erfordert die Uberpr¨ ufung¨ viele zus¨atzliche (bin¨are) Schlusselvergleiche¨ mit geringen Chancen, Duplikate fruh¨ zu entdecken, wenn diese nicht sehr h¨aufig auftreten. So musste¨ man in der Aufbauphase N/2 Bl¨atter, die im normalen Heapsort ubergangen¨ werden, zus¨atzlich paarweise auf Duplikate vergleichen, um die Vorbedingung herzustellen.

Entdeckt man im Heap ein Duplikat und ersetzt es durch das ¨außerste Blatt, kann dieses sowohl aufsteigen als auch absinken, oder wieder als Duplikat entdeckt werden. Ersetzt man Duplikate nicht und wandelt sie um in “L¨ocher”, analog zur Floyd-Verbesserung, k¨onnen dabei auch mehrere L¨ocher parallel im Heap entstehen. Die Situation wird dann schnell unubersichtlich.¨

4 / 23 Nachtrag Ruckblick¨ Ausblick Deapsort – eine praktikable L¨osung

Die folgende L¨osung ist aber praktikabel. Die neue Methode dsift(a, i, k) setzt auf der Methode von Floyd auf, d.h. ein Loch sinkt herab (nur Bruder-Vergleiche)¨ bis auf Blattebene. In dieser Phase werden keine Tests auf Duplikate vorgenommen.

Jetzt steigt der neu einzufugende¨ Schlussel¨ auf. Dabei testen wir auf Gleichheit, aber nur fur¨ Vater-Sohn-Knoten. Wird dabei ein Duplikat entdeckt, wird es aus dem Heap entfernt und wandert in die Folge der bereits entdeckten Duplikate. Das dadurch entstehende “Loch” sinkt jetzt wieder herab (ohne Duplikatsprufung)¨ wie vorher, auf Blattebene nehmen wir das ¨außerste Blatt und lassen es aufsteigen, auch wieder wie vorher.

5 / 23 Nachtrag Ruckblick¨ Ausblick Realisierung mittels Min-Heap

In der zweiten Phase des Deapsort, wenn wir kontinuierlich das Minimum entfernen, prufen¨ wir zus¨atzlich vor dem Anfugen¨ an die Folge der paarweise verschiedenen, jetzt sortierten Schlussel,¨ ob wir den Wert gerade schon gesehen haben. In dem Fall wandert der Satz naturlich¨ zu den Duplikaten.

Damit am Ende die Duplikate hinten stehen, bietet es sich an, einen Min-Heap zu konstruieren, dessen Wurzel ganz rechts liegt. Die folgende Abbildung 1 zeigt die Situation in Phase 1 (Baumaufbau) und Phase 2 (Minimumextraktion). Der Algorithmus hat knifflige Grenzf¨alle, etwa wenn das erkannte Duplikat zugleich das linkeste Blatt ist. Den Programmcode stellen wir auf die Web-Seite zur Vorlesung.

6 / 23 Nachtrag Ruckblick¨ Ausblick Phasen 1 und 2 in Deapsort

detected duplicate

duplicates heap under construction untreated u d j

sorted sequence duplicates heap u d j

Abbildung 1: Deapsort – Baumaufbau und Extraktion des Minimums

7 / 23 Nachtrag Ruckblick¨ Ausblick Bewertung

Ob Deapsort fur¨ diese Art der Sortierung mit gleichzeitiger Duplikatsentfernung am Ort eine Laufzeitreduzierung auf O(N log n) erreicht (n die Zahl der paarweise disjunkten Schlussel),¨ ¨ahnlich wie die Multimengensortierung mit Trisort und Linksort, w¨are noch zu zeigen. Die Baumaufbauphase ist klarerweise weiterhin linear in N.

Man kann Deapsort aber gut empirisch vergleichen mit einem Heapsort, dem sich eine Duplikatsentfernung am Ort auf der sortierten Folge anschließt. Das erh¨oht den Aufwand von Heapsort um O(N).

8 / 23 Nachtrag Ruckblick¨ Ausblick Vorteile Deapsort

Erste Messungen zeigen, dass der Zusatzaufwand fur¨ die Tests auf Gleichheit bei Deapsort eine deutliche Verschlechterung bringt, etwa in dem Umfang, wie wenn man von der Floyd-Verbesserung zuruckgeht¨ zum Original-Heapsort. Fur¨ un¨are und bin¨are Eingaben hat man dann tats¨achlich lineares Verhalten, aber diese F¨alle werden in der Praxis selten auftreten.

Insofern ist der Nutzen eher theoretischer Art. Ein Vorteil im Vergleich zu einer Duplikatsentfernung mittels Hashing, wie etwa DDT von Teuhola und Wegner [TW91], die im Mittel in O(N) l¨auft, besteht darin, dass die Unikate sortiert vorliegen. Damit schließen wir das Thema Deapsort.

9 / 23 Nachtrag Ruckblick¨ Ausblick Was nicht behandelt wurde I

Gegenub¨ er dem Turku-Skript wurden die Kapitel zu den stapellosen Quicksort-Varianten und zum Mischen zweier Folgen am Ort weggelassen. Beide sind eher von theoretischem Interesse und die Ausfuhrungen¨ zum zweiten Thema eher oberfl¨achlich.

Ganz ausgeblendet wurden praxisrelevante Varianten von Mergesort, Radixsort, Shellsort etc.

10 / 23 Nachtrag Ruckblick¨ Ausblick Was nicht behandelt wurde II

Auch nicht weiter behandelt wurde der Quicksort mit Doppelpivot aus der Java 7 Standardbibliothek, der auf Yaroslavskiy zuruckgeht.¨ Eine Analyse findet sich in [WN12], daruber¨ hinaus in sechs weiteren Arbeiten (Stand Mitte 2014) mit ann¨ahernd gleichem Titel der Autoren Wild und Nebel von der TU Kaiserslautern.

11 / 23 Nachtrag Ruckblick¨ Ausblick Einsichten – Fluktuation der Rechenzeiten

Das Messen von Laufzeiten galt schon immer als problematisch. Dies zeigt sich wieder in den Experimenten, wo derselbe Algorithmus mit denselben Eingaben unterschiedliche Werte liefert, die um 20 Prozent variieren k¨onnen. Ein Grund k¨onnte sein, dass moderne PCs w¨armeempfindlich sind und den Prozessor runtertakten bei hoher Belastung. Tats¨achlich belasten l¨angere Sorts in mehreren Durchl¨aufen mit Permutationserzeugung die Prozessoren erheblich.

Die Messgenauigkeiten selbst sind nicht schlecht, vermutlich sind die Werte bis zu 1/100 s genau. Ben¨otigt Quicksort fur¨ 10 Mio. S¨atze 2,71 s versus 4,28 s mit Heapsort, dann kann man diese relative Aussage durchaus als deutlichen Hinweis auf grundlegende Qualit¨aten mitnehmen (vgl. Abb. 2).

12 / 23 Nachtrag Ruckblick¨ Ausblick Beispiel fur¨ einsichtige Aussagen

Laufzeiten für N = 10.000.000 12,000

10,000

8,000

6,000 Sekunden

4,000

2,000

0,000 1 10 100 1000 10000 100000 1000000 10000000 M

Turku Lomuto Trisort Linksort

Abbildung 2: Laufzeiten aus Aufgabe 3 13 / 23 Nachtrag Ruckblick¨ Ausblick Einsichten – Einfluss des Cache

Die gr¨oßte Uberraschung¨ war der Einfluss moderner Prozessorarchitekturen auf die Rechenzeiten. Verfahren mit gutem Lokalit¨atsverhalten profitieren enorm vom Datencache. Deshalb kann es gunstiger¨ sein, Inhalte von S¨atzen (die Objekte selbst) physisch hin- und herzukopieren, statt nur die Zeiger auf die Objekte umzuordnen.

Ganz deutlich tritt dies bei den Verfahren Linksort und Trisort auf, die mit verketteten Listen arbeiten und einstmals rasend schnell waren, jetzt aber wegen der zuf¨allig im RAM verteilten Adressen hoffnungslos zuruckliegen.¨

Insofern ist es reizvoll, Verfahren wie Exquisit und Hillsort, die eigentlich fur¨ Plattensortierung gedacht sind und daher auf gutes Lokalit¨atsverhalten Wert legen, auf die Eignung als interne Verfahren zu untersuchen.

14 / 23 Nachtrag Ruckblick¨ Ausblick 1997 versus 2014 I

Sortierl¨aufe mit 1000 S¨atzen brauchten Ende der Siebziger auf Rechnern der PDP-11-Klasse ungef¨ahr eine Sekunde. Die Preise dieser kleinen 16-Bit-Forschungsrechner fingen damals bei US$ 10.000 an und reichten schnell an US$ 50.000 heran. Fur¨ Forschungsarbeiten zu Sortierverfahren uberlies¨ IBM dem Verfasser dieser Zeilen einen PS/2 Rechner, Modell 80, ein etwas seltsames Modell mit einem Intel 80286 Prozessor (noch 16-Bit), der an einem 32-Bit Microchannel-Bus hing. Die Leistung des PC lag aber deutlich uber¨ der eines PDP-11 Rechners. Fur¨ eine Speichererweiterung von einem auf vier MB wurde eine Steckkarte mit 3 MB RAM erworben, die 3.000,- DM kostete!

Wie die Ubungen¨ zeigen, lassen sich heute intern etwa 10 Mio. S¨atze in etwas uber¨ einer Sekunde sortieren – auf einem PC vom Discounter! We’ve come a long way baby ...

15 / 23 Nachtrag Ruckblick¨ Ausblick 1997 versus 2014 II

In einer Arbeit aus dem Jahr 1997 mit dem Titel “A Meticulous Analysis of Mergesort Programs” untersuchen Jyrki Katajainen und Jesper Larsson Tr¨aff haupts¨achlich Mergesort-Varianten, messen aber auch einen Quicksort und einen Heapsort [KT97]. Die Laufzeiten wurden auf einer fur¨ damalige Zeiten flotten Sun SPARCstation 4 mit 85 MHz Taktfrequenz und 64 MB RAM als C-Programme getestet. Einen Tabellenaussschnitt aus [KT97, S. 226] fur¨ 5 Mio. Integer zeigen wir unten (Tabelle 1). Hinzugefugt¨ haben wir eine Messung von heute fur¨ unsere Varianten (hier in Pascal) auch fur¨ 5 Mio. S¨atze mit Schlussel-¨ und Infofeld gem¨aß unserer Vorgaben.

16 / 23 Nachtrag Ruckblick¨ Ausblick 1997 versus 2014 III

Tabelle 1: Zwei Resultate aus den Jahren 1997 und 2014.

Experiment mergesort two-way four-way quicksort heapsort N = 5.000.000 (textbook) (improved) (pointers) (iterativ) [KT97] Zeit (ms) 23440 18120 9810 16780 43460 Schl.-vergl. 107002936 112002935 119544746 152193888 113150419 Vorlesung 2014 Zeit (ms) – –– 829 1804 Schl.-vergl. – – – 127826269 113150808

Man beachte die Ubereinstimmung¨ bei den Schlusselvergleichen¨ fur¨ den Heapsort. Der von K&T gew¨ahlte Quicksort scheint aber keine schnelle Variante zu sein, trotz des Hinweises auf “iterativ”.

17 / 23 Nachtrag Ruckblick¨ Ausblick Dreiwegevergleiche

Wie ein roter Faden zieht sich das Thema Multimengen und Duplikatsentdeckung durch die Lektionen. In Lektion 4 reiten wir auf der Unterscheidung zwischen fruher¨ Duplikatsentdeckung mit Trisort und sp¨ater Entdeckung mit Linksort herum, weil die Dreiteilung mit den bin¨aren Vergleichen in Pascal oder Java teuer ist. Muss das so sein?

18 / 23 Nachtrag Ruckblick¨ Ausblick Geschachteltes if-then-else

Was macht ein optimierender Compiler aus diesem Codefragment?

Listing 1: Geschachteltes if-then-else. i f a[i].key < H then begin ... end e l s e i f a[i].key = H then begin ... end e l s e {a[i].key > H } begin ... end ; Mit Gluck¨ etwas in der Form CMP Op1 Op2 JLT Addr1 JEQ Addr2 #Code f¨ur den Fall > H ...

19 / 23 Nachtrag Ruckblick¨ Ausblick Dreiwegevergleiche I

Nach Kenntnis des Verfassers dieser Folien liefert eine CMP Op1, Op2-Instruktion (compare Operand1, Operand2) immer ein Resultat in einem Flag-Register ab, aus dem z.B. fur¨ Integer-Operanden auf <, =, > geschlossen werden kann. Darauf folgende bedingte Sprungbefehle, z.B. ein JLE oder BLE, also jump on less or equal, branch on less or equal haben als Operanden dann ein Sprungziel, zu dem verzweigt wird, wenn die Bedingung erfullt¨ ist. Ist sie nicht erfullt,¨ f¨ahrt die Abarbeitung mit der folgenden Instruktion fort.

Die oben gezeigte Optimierung ist dann kaum aufwendiger als ein bin¨arer Vergleich und vermutlich schneller als eine Verzweigung uber¨ Sprungtabellen.

20 / 23 Nachtrag Ruckblick¨ Ausblick Dreiwegevergleiche II

Das wurde¨ auch die Frage beantworten, warum es keine bedingten Sprunge¨ mit zwei Sprungzielen gibt, etwa in der Form J3LE R1, R2 mit indirekten Sprungen¨ uber¨ zwei Sprungregister R1, R2, so dass z.B. bei Vergleichsresultat -1 nach [R1], bei 0 nach [R2] verzweigt wird und bei +1 der Instruktionsz¨ahler weitergez¨ahlt wird.

Auf der sicheren Seite w¨are man als Programmierer, wenn in den Hochsprachen explizite Dreiwegevergleiche angeboten wurden.¨ Dies ist nur in einigen exotischen Sprachen der Fall, die Sprache C bietet nur ein strcmp fur¨ Zeichenketten an, das ein dreiwertiges Resultat liefert, das dann ggf. uber¨ eine case-Anweisung weiterverarbeitet werden kann.

21 / 23 Nachtrag Ruckblick¨ Ausblick Dreiwegevergleiche III

Dreiwegevergleiche der obigen Art h¨atten einen gewissen Einfluss auf die Algorithmik. Verfahren wie Trisort oder der gerade besprochene Deapsort lieferten bei geeigneter Programmierung effektive Duplikatsentdeckung ohne Aufpreis. Fur¨ das andere große Thema, die hier zu kurz gekommene Beschleunigung bei Vorsortierung, w¨aren Dreiwegevergleiche nicht von Vorteil, sind dann aber auch nicht von Nachteil.

22 / 23 Nachtrag Ruckblick¨ Ausblick Literatur

[KT97] Jyrki Katajainen and Jesper Larsson Tr¨aff, A meticulous analysis of mergesort programs, CIAC (Gian Carlo Bongiovanni, Daniel P. Bovet, and Giuseppe Di Battista, eds.), Lecture Notes in Computer Science, vol. 1203, Springer, 1997, pp. 217–228. [TW91] Jukka Teuhola and Lutz Michael Wegner, Minimal space, average linear time duplicate deletion, Commun. ACM 34 (1991), no. 3, 62–73. [WN12] Sebastian Wild and Markus E. Nebel, Average case analysis of java 7’s dual pivot quicksort, ESA (Leah Epstein and Paolo Ferragina, eds.), Lecture Notes in Computer Science, vol. 7501, Springer, 2012, pp. 825–836.

23 / 23