Zum Inhalt springen
L

Das Video kommt von YouTube: erst beim Abspielen verbindet sich die Seite mit YouTube (Google).

Quicksort Algorithmus [mit Animation, Deutsch]

HappyCoders11:12 33.412 Aufrufe veröffentlicht Auf YouTube

Das Wichtigste aus dem Video

Tipp auf eine Zeit – das Video springt genau dorthin.

Transkriptautomatisch erstellt · 81 Zeilen
Herunterladen
  1. In diesem Video zeige ich euch, wie Quicksort funktioniert, was ein Pivot-Element ist und wie man es festlegt und wie man die Zeitkomplexität von Quicksort bestimmt.
  2. Wir wollen diese neun Zahlen mit Quicksort sortieren. Dazu teilen wir die Zahlen in zwei Bereiche auf: einen mit kleinen Zahlen und einen mit
  3. großen Zahlen. Und danach sortieren wir diese Bereiche – in sich – wiederum mit Quicksort. Aber was sind kleine und große Zahlen?
  4. Um diese voneinander abzugrenzen, legen wir ein sogenanntes “Pivot-Element” fest. Dafür gibt es verschiedene Strategien – zu denen kommen wir später.
  5. Die einfachste ist: Wir verwenden immer das Element ganz rechts – im Beispiel also die 6.
  6. Kleine Zahlen sind jetzt alle Zahlen, die kleiner als 6 sind und große Zahlen sind die, die größer oder gleich 6 sind.
  7. Um die Zahlen in zwei Bereiche aufzuteilen, gehen wir wie folgt vor: Wir suchen von links beginnend nach dem ersten Element, das größer oder gleich 6 ist.
  8. Die 3 ist es nicht; die 7 ist größer als 6. Und von rechts beginnend, suchen wir das erste Element, das kleiner als 6 ist.
  9. Das Pivot-Element selbst überspringen wir. Und mit der 4 haben wir die erste Zahl kleiner als 6 gefunden.
  10. Jetzt tauschen wir die 7 und die 4, so dass die 4 im linken Bereich landet und die 7 im rechten.
  11. Wir suchen von links das nächste Element, das größer oder gleich 6 ist. Die 1 ist es nicht; die 8 ist größer als 6.
  12. Und von rechts das nächste Element kleiner als 6. Die 9 ist nicht kleiner, die 5 ist kleiner.
  13. Wir tauschen also die 8 und die 5. Wir setzen die Suche von links fort. Bei der 2 angekommen stehen die Suchpositionen direkt
  14. nebeneinander, d. h. dass wir keine weiteren Elemente tauschen müssen. Die 2 ist kleiner als das Pivot-Element und gehört damit in den linken Bereich.
  15. Entsprechend fügen wir eine gedankliche Trennlinie rechts von der 2 ein. Und jetzt sind alle Elemente im linken Bereich kleiner als 6 – und alle Elemente rechts
  16. größer als 6. Ein letzter Schritt fehlt noch bei der Aufteilung. Und zwar wissen wir an dieser Stelle, dass
  17. alle Elemente im rechten Block größer oder gleich dem Pivot-Element sind – so haben wir sie hier ja einsortiert.
  18. Im Umkehrschluss ist das Pivot-Element also das kleinste Element des rechten Bereichs – bzw. eines der kleinsten, wenn der Bereich mehrere Sechsen enthalten würde.
  19. Wenn wir das Pivot-Element nun mit dem ersten Element des rechten Bereichs tauschen, dann liegt es automatisch auf seiner endgültigen Position. Und wir müssen nur noch die Bereiche
  20. links und rechts des Pivot-Elements sortieren. Wir machen mit dem linken Bereich weiter und bestimmen zunächst wieder das Pivot-Element.
  21. Entsprechend unserer Pivot-Strategie nehmen wir wieder das letzte Element des Bereichs – die 2.
  22. Wir suchen wieder von links aus das erste Element, das größer oder gleich 2 ist. Das ist direkt das erste, die 3. Und von rechts aus, das erste Element kleiner als 2 – das
  23. ist die 1. Wir tauschen die 3 mit der 1.
  24. Die linke Suchposition wandert noch ein Feld nach rechts und steht damit direkt neben der rechten Suchposition. Wir müssen also keine weiteren Elemente tauschen.
  25. Die 4 ist größer als das Pivot-Element, gehört damit in den rechten Bereich; und entsprechend ziehen wir die Trennlinie links von der 4.
  26. Wir tauschen wieder das Pivot-Element mit dem linken Element des rechten Bereichs und trennen auch den Bereich rechts vom Pivot-Element ab.
  27. Der linke Teilbereich enthält nur die 1 und gilt damit als sortiert. Im rechten Teilbereich wählen wir wieder das Pivot-Element – die 4.
  28. Wir suchen von links aus das erste Element größer oder gleich 4 – das ist die 5. Damit sind wir auch schon am rechten Rand angekommen, und müssen von rechts nicht mehr
  29. suchen. Da die 5 größer als das Pivot-Element ist, ziehen wir die Trennlinie links davon.
  30. Im rechten Teilbereich tauschen wir das Pivot-Element mit dem linken Element – und trennen auch den Bereich rechts vom Pivot-Element ab.
  31. Und jetzt haben wir im gesamten linken Bereich nur noch Pivot-Elemente und Teilbereiche, die genau ein Element enthalten.
  32. Der linke Bereich ist damit fertig sortiert. Kommen wir zum rechten Bereich.
  33. Wir wählen wieder das Pivot-Element. Wir suchen von links das erste Element, das größer oder gleich 8 ist. Das ist direkt
  34. das erste Element, die 9. Und von rechts suchen wir das erste Element, das kleiner als 8 ist. Das ist die 7, und wir tauschen diese mit der 9.
  35. Die Suchpositionen sind aufeinander getroffen, und wir ziehen die Trennlinie dazwischen. Im rechten Bereich tauschen wir wieder das Pivot-Element mit dem linken Element und trennen
  36. den Bereich rechts davon ab. Jetzt haben wir auch im rechten Bereich nur noch Pivot-Elemente und Teilbereiche mit nur
  37. einem Element. Auch der rechte Bereich ist damit fertig sortiert – und damit die gesamte Liste.
  38. Der Quicksort-Algorithmus ist damit beendet. Zu Beginn des Videos habe ich erwähnt, dass es verschiedene Pivot-Strategien gibt.
  39. Im eben gezeigten Beispiel haben wir immer das ganz rechte Element als Pivot-Element gewählt.
  40. Alternative Strategien sind: das mittlere Element; das linke Element; ein zufälliges Element, der Median aus drei Elementen, z. B. dem ersten, mittleren und letzten – oder
  41. der Median aus fünf oder sogar sieben Elementen. Das Ziel ist es, das Pivot-Element so zu wählen, dass die Eingabe in zwei möglichst gleich
  42. große Bereiche aufgeteilt wird. Bei zufällig verteilten Eingabezahlen macht es keinen Unterschied, ob man das linke, mittlere
  43. oder rechte Element wählt. Nimmt man den Median aus drei Zahlen, dann erhöht man die Wahrscheinlichkeit, dass die
  44. Bereiche ähnlich groß sind. Sind die Eingabeelemente jedoch vorsortiert, kann es zu Problemen kommen.
  45. Nehmen wir diese Eingabe. Wenn wir das rechte Element, also die 9, als Pivot-Element wählen, dann hat nach der Partitionierung
  46. der linke Bereich acht Elemente und der rechte gar keine. Wenn wir dann den linken Bereich partitionieren, erhalten wir einen Bereich mit sieben Elementen.
  47. Dann einen mit sechs, mit fünf, mit vier, usw. Insgesamt müssen wir acht mal partitionieren. Das ist doppelt so viel wie bei den zufällig verteilten Zahlen, bei denen wir nur vier
  48. mal partitioniert haben. Das gleiche passiert, wenn wir das linke Element als Pivot-Element verwenden – oder wenn
  49. die Bereiche absteigend vorsortiert sind. Wenn also die Möglichkeit besteht, dass unsere Eingabezahlen vorsortiert sind, dann sollten
  50. wir auf keinen Fall das linke oder rechte Element als Pivot-Element wählen, sondern das mittlere, ein zufälliges oder den Median aus mehreren Elementen.
  51. Kommen wir zur Zeitkomplexität von Quicksort – und zwar zuerst zum worst case, den wir eben bei den vorsortierten Elementen gesehen haben.
  52. Die Anzahl der zu sortierenden Elemente bezeichnen wir mit “n”. Im folgenden Beispiel ist n gleich sieben.
  53. Bei der ersten Partitionierung vergleichen wir sechs Elemente mit dem Pivot-Element. . Es entsteht ein einziger Bereich mit sechs
  54. Elementen. Bei der zweiten Partitionierung vergleichen wir fünf Elemente mit dem Pivot-Element.
  55. Bei der dritten Partitionierung vergleichen wir vier Elemente, bei der vierten drei Elemente, bei der fünften zwei Elemente und bei der sechsten noch ein Element.
  56. In der Summe kommen wir auf 21 Vergleiche. Das kann man auch wie folgt ausrechnen: sieben Elemente mal sechs Partitionierungsschritte
  57. – geteilt durch zwei, da pro Partitionierungsschritt im Durchschnitt die Hälfte der Elemente verglichen wird.
  58. Sieben mal sechs ist 42 – geteilt durch zwei ist 21. Wenn wir “sieben” wieder durch “n” ersetzen, ergibt das: n × (n-1) × ½
  59. Ausmultipliziert ergibt das: ½ (n² – n) Für die Notierung der Zeitkomplexität ist nur die höchste Potenz von n relevant, also
  60. n². Die Zeitkomplexität von Quicksort ist also im worst case (auf deutsch: im schlechtesten
  61. Fall): O von n Quadrat. O von n Quadrat … oder auch “quadratischer Aufwand” bedeutet: Die benötigte Zeit wächst
  62. im Quadrat mit der Anzahl der zu sortierenden Elemente. Als nächstes schauen wir uns den best case an. Im besten Fall sind die bei der Partitionierung
  63. entstehenden Bereiche immer gleich groß. Hier wieder unser Beispiel mit sieben Elementen.
  64. Bei der ersten Partitionierung vergleichen wir sechs Elemente mit dem Pivot-Element; und es entstehen zwei Bereiche mit jeweils drei Elementen.
  65. Bei der Partitionierung des linken und rechten Bereichs vergleichen wir jeweils zwei Elemente mit den jeweiligen Pivot-Elementen. Es entstehen vier Bereiche der Größe eins.
  66. Und damit sind wir auch schon fertig. In der Summe kommen wir auf nur zehn Vergleiche. Im worst case waren es 21.
  67. Aber wie verpacken wir das jetzt in eine Formel? Wir haben hier zum einen mehrere Ebenen und zum anderen eine Anzahl von Vergleichen und
  68. ggf. Vertauschungen pro Ebene. Wenn wir die Anzahl der Elemente auf 14 verdoppeln, dann müssen wir nur eine Zeile hinzufügen;
  69. und die Anzahl der Vergleiche pro Zeile verdoppelt sich … ungefähr (in diesem Beispiel ist es jeweils einer weniger als das Doppelte).
  70. Wenn wir mit nur einer zusätzlichen Partitionierungsebene doppelt so viele Elemente sortieren können, entspricht im Umkehrschluss die Anzahl der Partitionierungsebenen dem Zweierlogarithmus
  71. von n. Für die O-Notation kann die Basis wegfallen, und wir erhalten: O(log n)
  72. Die Anzahl der Operationen pro Partitionierungsebene wächst, wie wir gesehen haben, linear mit n.
  73. So wie man die Fläche eines Rechtecks durch Multiplikation von Breite und Höhe berechnet, können wir für den Gesamtaufwand die Operationen pro Partitionierungsebene mit der Anzahl der
  74. Ebenen multiplizieren. Als Zeitkomplexität für den Best Case ergibt sich also: O von n mal log n
  75. Wir nennen diese Komplexitätsklasse auch “quasilinearen” Aufwand, da bei großen n der logarithmische Anteil kaum noch ins Gewicht fällt und die Kurve kaum noch von
  76. einer Linearen zu unterscheiden ist. Auch im average case, also im durchschnittlichen Fall, lautet die Zeitkomplexität O von n
  77. log n. Der Nachweis ist allerdings … recht kompliziert und würde den Rahmen dieses Videos sprengen.
  78. Ich hoffe euch hat diese Erklärung von Quicksort gefallen. Ihr findet die Erklärung nochmal zum Nachlesen auf meiner Webseite HappyCoders.eu. Einen Link gibt es in der Videobeschreibung.
  79. In dem Artikel findet ihr auch den Quellcode von Quicksort und die Beschreibung einer fortgeschrittenen Quicksort-Variante, dem Dual-Pivot-Quicksort.
  80. Wenn euch das Video gefallen hat, dann freue ich mich über einen Daumen hoch oder einen Kommentar, und natürlich auch, wenn ihr meinen Kanal abonniert.
  81. Bis bald und Happy Coding!

Zum Nachlesen