Quicksort

Page Shortcuts

Gebrauch

Der Quicksort wird gebraucht, um einen Array zu sortieren.

Der Quicksort kann sehr effizient sein, er kann jedoch im schlechtesten Fall genauso ineffizient wie die einfacheren Sortieralgorithmen sein.

Spezifikationen

Beim Quicksort werden im schlechtesten Fall, der aber nur sehr selten vorkommt O(n2) Vergleiche durchgeführt. Die best-case Performance besteht aus O(n * log(n)) Vergleichen. Seine Durchschnittsperformance beträgt O(n * log(n)) Vergleiche.

Der Algorithmus funktioniert als In-place-Algorithmus, da er nur Elemente innerhalb einer Liste vertauscht. Jedoch braucht er für jede Rekursionsebene neuen Speicherplatz und hat damit eine durchschnittliche Space-complexity von O(log(n)) und im schlechtesten Fall eine Space-complexity von O(n).

Funktionsweise

Der Quicksort Algorithmus arbeitet nach dem Teile-und-herrsche-Verfahren.

Das Grundprinzip vom Teile-und-herrsche-Verfahren ist, dass ein Problem, welches sehr schwierig erscheint, so lange in einfachere Teilprobleme zerlegt wird, bis diese beherrschbar, also gelöst sind. Dieses Verfahren kann von einer rekursiven Funktion, also einer Funktion, die sich selber aufruft, durchgeführt werden. Die Lösung des letzten Teilproblems ist dabei auch die Lösung des Gesamtproblems.
Der Quicksort führt dieses Teile-und-herrsche-Verfahren aus, indem er einen unsortierten Array, also das Problem in zwei unsortierte Teilarrays unterteilt. Dies macht er indem er ein beliebiges Element als das sogenannte Pivot-Element definiert. Das Pivot-Element kann am Ende des Arrays stehen, wie beispielsweise im Beispielcode, kann aber auch in der Mitte oder zufällig an einem beliebigen Index innerhalb des zu sortierenden Teilarrays gewählt werden. Der Algorithmus vertauscht die Elemente des Arrays nun so, dass zwei neue Teilarrays entstehen, einer mit Elementen, die alle kleiner oder gleich wie gross das gewählte Pivot-Element sind und der andere mit Elementen, die alle grösser oder gleich dem Pivot-Element sind. Dies kann dadurch gemacht werden, indem für jedes Element getestet wird, ob es kleiner als das Pivot-Element ist oder nicht. Ist es kleiner, dann wird es mit dem ersten Element getauscht, das diese Bedingung nicht erfüllt hat und somit grösser oder gleich dem Pivot-Element sein muss. Wurde der Array in die zwei Teilarrays unterteilt wird das Pivot-Element dazwischengesetzt und befindet sich somit an seiner endgültigen Position. Dieses Verfahren wird nun durch Rekursion auf jeden Teilarray angewandt, bis alle Teilarrays aus lediglich noch einem Element bestehen. Ist dies der Fall ist der Array sortiert.

Beispielcode

Dies ist ein in Python geschriebener Beispielcode:

# arr ist der Array, welcher zu sortieren ist, low der Index des ersten Elements und high der Index des letzten Elements def quickSort(arr, low, high): # Abbruchbedingung, wenn der Array fertig sortiert ist, damit die Funktion nicht unendlich lange läuft if low < high: # Der Index des Elementes auf dem unsortierten linken Teil des Arrays low_index = low # Element, mit dem verglichen wird hat den höchsten Index im Teilarray pivot = arr[high] # Es wird von low bis (und ohne) dem Pivot Element jedes Element mit dem Pivot-Element verglichen for high_index in range(low, high, 1): # Falls der untersuchte Wert kleiner als das Pivot-Element ist if arr[high_index] < pivot: # Die beiden Werte werden miteinander getauscht arr[low_index], arr[high_index] = arr[high_index], arr[low_index] # Low_index wird erhöht, da dieses Element nun kleiner ist als das Pivot Element low_index += 1 # Das Pivot-Element wird dorthin gesetzt wo rechts alle grösser und links alle kleiner sind arr[low_index], arr[high] = arr[high], arr[low_index] # Die Funktion wird mit dem teilsortierten Array erneut aufgerufen und der rechte Teil wird sortiert quickSort(arr, low_index + 1, high) # Die Funktion wird mit dem teilsortierten Array erneut aufgerufen und der linke Teil wird sortiert quickSort(arr, low, low_index - 1) # Der sortierte Array wird zurückgegeben return arr

Dies ist ein in Java geschriebener Beispielcode:

Es können selbstverständlich auch andere Datentypen gebraucht werden.

// arr ist der Array, welcher zu sortieren ist. Die Funktion gibt den sortierten Array zurück public static int quicksort(int[] arr, int low, int high) { // Abbruchbedingung, wenn der Array fertig sortiert ist, damit die Funktion nicht unendlich lange läuft if (low < high) { // Der Index des Elementes auf dem unsortierten linken Teil des Arrays int low_index = low; // Das Pivot-Element des Teilarrays wird an dessen Ende gewählt int pivot = arr[high]; // Es wird von low bis zu dem Pivot-Element jedes Element mit dem Pivot-Element verglichen for (int high_index = low; high_index < high; high_index++) { // Falls der untersuchte Wert kleiner als das Pivot-Element ist if (arr[high_index] < pivot) { // Die beiden Werte werden miteinander getauscht int temp = arr[high_index]; arr[high_index] = arr[low_index] ; arr[low_index] = temp; // Low_index wird erhöht, da dieses Element nun kleiner als das Pivot-Element ist low_index++; } } // Das Pivot-Element wird an die Position gebracht, an der links alle kleiner und rechts alle anderen Elemente grösser sind int temp = arr[low_index]; arr[low_index] = arr[high]; arr[high] = temp; // Die Funktion wird mit dem teilsortierten Array erneut aufgerufen und der rechte Teil wird sortiert quickSort(arr, low_index + 1, high); // Die Funktion wird mit dem teilsortierten Array erneut aufgerufen und der linke Teil wird sortiert quickSort(arr, low, low_index - 1 } // Der sortierte Array wird zurückgegeben return arr; }

Animiertes Beispiel

Legende

  • Das Pivot-Element, mit dem verglichen wird und von dem die einzelnen Teilarrays abgetrennt werden
  • Momentan nicht beachteter Wert
  • Wird mit Pivot verglichen und mit dem blauen Element getauscht, falls es kleiner als das Pivot-Element ist
  • Wird mit dem grauen Element getauscht, falls dies verlangt wird.
  • Wird mit dem Pivot-Element getauscht, falls dies verlangt wird. Links davon sind also alle kleiner als das Pivot-Element und rechts alle grösser.

Drücke Start, um die Animation zu starten. Ändere die Position des Sliders, um die Geschwindigkeit der Animation zu verändern.