31.2
Quicksort 31.2.1 Die Idee |
|||||||||||||||||||||||||||||||
Quicksort |
|
||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||
Im ersten Schritt des Qicksort bestimmt man aus der Liste zunächst eine Zahl als so genannten Trenner (Angelpunkt engl. pivot), z.B. die Zahl 60 auf Platz der Nr. 4. |
|||||||||||||||||||||||||||||||
Der Name
Trenner rührt daher, dass er benutzt wird, aus der Liste zwei Teillisten
so zu erzeugen. Dabei werden Teillisten so konstruiert, dass in der
linken Teilliste nur Zahlen stehen,
die kleiner als der Trenner, und damit kleiner 60 sind. Die Zahlen, die
größer als der Trenner, und damit größer als 60 sind, finden in der
rechten Teilliste ihren Platz. Der
Trenner selbst gehört dann zu keiner Teilliste mehr.
Nach dem Aufteilen in zwei Teillisten hätte unsere Liste die folgende Gestalt: |
|||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||
Es sei darauf aufmerksam gemacht, dass der Trenner seinen Platz in der sortierten Liste bereits jetzt eingenommen hat. Mit den beiden Teillisten verfahren wir auf die gleiche Weise wie mit der Ausgangsliste. |
|||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||
In den Zeilen der oben dargestellten Tabelle sind die Einträge in der Liste so eingetragen, dass der Sortiervorgang etwas deutlicher wird. So stehen in der ersten Zeile die bereits sortierte Elemente, es sind die Elemente, die schon einmal Trenner waren. In der zweiten Zeile sind die Trenner der neuen Teillisten für den nächsten Schritt markiert. In der dritten Zeile schließlich erkennt die Teillisten der „nächsten Generation“. |
|||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
Enthält eine Liste nur noch ein Element, dann ist sie a priori sortiert | |||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
Wir sind am
Ende angekommen, wenn die Teillisten nur noch ein Element enthalten.
Es bleiben
zwei Fragen. |
|||||||||||||||||||||||||||||||
Trenner finden | pivot =liste[((untereGrenze+obereGrenze) / 2)]; | ||||||||||||||||||||||||||||||
wegen der Ganzzahldivision „pivot“ in beiden Fällen der Trenner ist. (Die ganze Liste ist wieder als Reihung realisiert und hat dabei den Namen „liste“. Die ganze Liste, aber auch jede Teilliste wird dann über Platznummern „obereGrenze“ und „untereGrenze“ festgelegt.
|
|||||||||||||||||||||||||||||||
Erzeugen der Teillisten | Kommen
wir zu der schwierigeren Frage: Wie erzeugt man die beiden Teillisten? Wie
erklären den Algorithmus an der gleichen Ausgangsliste. Die Variablen „links“
und „rechts“
zeigen zunächst wie untereGrenze
(uG) und
obereGrenze
(oG) auf Anfang bzw. Ende der Reihung.
links = untereGrenze; (Anmerkung: Beim ersten Aufruf des Trennens der Urliste müssen untereGrenze und obereGrenze auf 0 bzw. auf liste.length-1 gesetzt werden) |
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
links wandert nun solange nach rechts, bis seine Zelle eine Zahl enthält, die größer ist als pivot. rechts wandert solange nach links, bis seine Zelle eine Zahl enthält, die kleiner ist als pivot.
while
{
bzw |
|||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
links und rechts tauschen nun ihre Zelleninhalte aus. . |
|||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||
links und rechts wandern weiter bis zu den nächsten Tauschpositionen und übergehen dabei Zellen, deren Inhalte sch bereits in den richtigen Teillisten befinden. Beobachten wir bereits in unsere Liste unmittelbar vor. Nach dem nächsten Tausch sieht die Liste so aus: |
|||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||
Das "Wandern" von „links“ und „rechts“ hat dann ein Ende, wenn „rechts“ links von „links“ steht. Das Erzeugen der Teillisten für den Trenner 60 ist fertig: | |||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||
Die linke Teilliste ist durch die Positionen uG und rechts, die rechte Teilliste durch die Positionen links und oG festgelegt. Das Sortieren dieser neuen Teillisten erfolgt durch den rekursiven Aufruf des Algorithmus mit den neuen Grenzen als Übergabeparameter. |
|||||||||||||||||||||||||||||||
if
(untereGrenze < rechts) {
In der
if-Klausel
steckt die Abbruchbedingung für den rekursiven Abstieg. Ist nämlich
obereGrenze == rechts
bzw.
links == untereGrenze,
so enthalten die Listen nur noch ein Element und sind somit a priori
sortiert. |
|||||||||||||||||||||||||||||||
Zusammenfassung | In einer
Vorstufe zur Normsprache lässt sich der Algorithmus gut auf den Punkt
bringen:
Sortiere(Liste, von bis): Der wesentlich Punkt dabei ist die Forderung, dass nach
dem Partitionieren alle Elemente links vom pivot KLEINER (oder GLEICH)
sind als dieser, und alle Elemente rechts davon GRÖSSER (oder gleich). |
||||||||||||||||||||||||||||||
zu | 31.2.2 Implementierung | ||||||||||||||||||||||||||||||
zur Startseite | www.pohlig.de (C) MPohlig 2004 |