Heapify All The Things With Heap Sort
Jemand sagte mir einmal, dass alles Wichtige in der Informatik auf Bäume hinausläuft. Buchstäblich nur Bäume. Wir können sie benutzen, um Dinge zu bauen, Dinge zu analysieren und Dinge zu interpretieren (ja, hier wird vielleicht etwas vorweggenommen, machen Sie sich keine Sorgen, wenn es für Sie noch keinen Sinn ergibt, denn das wird es bald!) Und wir können sie sogar benutzen, um – du hast es erraten! – Dinge zu sortieren.
Ah, sortieren. Wir haben in den letzten Wochen so viel sortiert, aber wir nähern uns jetzt dem Ende unseres Sortierabenteuers. Es ist jedoch unmöglich und unfair, über das Sortieren zu sprechen, ohne auf eine besondere Art des Sortierens einzugehen, bei der die neueste Datenstruktur in unserem Datenstruktur-Werkzeuggürtel zum Einsatz kommt.
Wir haben vor kurzem gelernt, Heaps zu lieben, eine besondere Art von Binärbaum, der einem strengen Regelwerk folgt und zur Implementierung von Dingen wie Prioritätswarteschlangen und Hintergrundjobs verwendet wird. Aber das sind nicht die einzigen Dinge, für die Heaps gut sind. Es stellt sich heraus, dass binäre Heaps oft zu keinem anderen Zweck als zum effizienten Sortieren verwendet werden. Viele Programme verlassen sich auf die Heap-Sortierung, da sie eine der effizientesten Möglichkeiten ist, ein Array zu sortieren. Und da wir nun wissen, was ein Heap ist, können wir versuchen zu verstehen, warum er so gut funktioniert, wenn es um das Problem des Sortierens geht!
Bevor wir uns in die Heap-Sortierung stürzen, sollten wir sicherstellen, dass wir Heaps richtig im Kopf haben. Wir erinnern uns vielleicht daran, dass ein Heap eigentlich nichts anderes ist als ein Binärbaum mit einigen zusätzlichen Regeln, die er befolgen muss: Erstens muss er immer eine Heap-Struktur haben, bei der alle Ebenen des Binärbaums von links nach rechts aufgefüllt werden, und zweitens muss er entweder als Max Heap oder als Min Heap geordnet sein. Für die Zwecke der Heap-Sortierung werden wir uns ausschließlich mit Max-Heaps beschäftigen, bei denen jeder Elternknoten (einschließlich der Wurzel) größer oder gleich dem Wert seiner Kinderknoten ist.
Okay, kommen wir zur Beantwortung der Frage der Stunde: Wie sortiert man mit Heaps? Nun, um diese Frage zu beantworten, müssen wir zunächst verstehen, was ein Heap-Sortieralgorithmus ist!
Ein Heap-Sortieralgorithmus ist eine Sortiertechnik, die sich auf binäre Heap-Datenstrukturen stützt. Da wir wissen, dass Heaps immer einer bestimmten Reihenfolge folgen müssen, können wir uns diese Eigenschaft zunutze machen, um das größte Element mit dem höchsten Wert zu finden und die Elemente nacheinander zu sortieren, indem wir den Wurzelknoten eines Heaps auswählen und ihn an das Ende des Arrays anhängen.
Wir wissen bereits, dass Heap-Sortierung eine effiziente Methode ist, um ein unsortiertes Array zu sortieren; aber was hat ein Array mit einem Heap zu tun? Und wie sortiert man ein Array mit einem Heap? Nun, es gibt drei Schlüsselschritte, wie das in der Praxis funktioniert. Wir werden uns diese in einem Moment genauer ansehen, aber lassen Sie uns zunächst einen kurzen Blick auf diese drei Schritte werfen.
- Zu Beginn haben wir ein unsortiertes Array. Der erste Schritt besteht darin, dieses Array in einen Heap zu verwandeln; in unserem Fall wollen wir es in einen Max Heap verwandeln. Wir müssen also die Daten unseres unsortierten Arrays transformieren und einen Max Heap erstellen. Normalerweise wird dies durch eine einzige Funktion gekapselt, die etwa so heißen könnte:
buildMaxHeap
. - Wenn wir unsere Array-Daten in einem Max-Heap-Format haben, können wir sicher sein, dass der größte Wert am Wurzelknoten des Heaps liegt. Denken Sie daran, dass, auch wenn der gesamte Heap nicht sortiert ist, wenn wir unseren Max Heap korrekt und fehlerfrei aufgebaut haben, jeder einzelne Elternknoten in unserem Heap einen größeren Wert hat als seine Kinder. Wir verschieben also den größten Wert – der sich am Wurzelknoten befindet – an das Ende des Heaps, indem wir ihn mit dem letzten Element vertauschen.
- Jetzt befindet sich das größte Element im Heap am letzten Knoten, was großartig ist. Wir wissen, dass es sich an seiner sortierten Position befindet, so dass es vollständig aus dem Heap entfernt werden kann. Aber es gibt noch einen weiteren Schritt: Wir müssen sicherstellen, dass sich das neue Element des Wurzelknotens an der richtigen Stelle befindet! Es ist höchst unwahrscheinlich, dass sich das Element, das wir in die Position des Wurzelknotens verschoben haben, an der richtigen Stelle befindet. Daher verschieben wir das Element des Wurzelknotens nach unten an die richtige Stelle, wobei wir eine Funktion verwenden, die normalerweise so etwas wie
heapify
.
heißt, und das ist im Grunde alles! Der Algorithmus wiederholt diese Schritte, bis der Heap nur noch aus einem einzigen Knoten besteht. Zu diesem Zeitpunkt weiß er, dass sich alle Elemente in der unsortierten Anordnung an ihren sortierten Positionen befinden und dass der letzte verbleibende Knoten das erste Element in der sortierten Anordnung sein wird.
Okay, ich weiß, dass ich gesagt habe, dass dies die einzigen drei Schritte der Haufensortierung sind. Aber wenn Ihnen diese drei Schritte verwirrend erscheinen, machen Sie sich keine Sorgen; sie können ziemlich kompliziert und schwer zu verstehen sein, bis Sie sie in Aktion sehen. Ich glaube sogar, dass dieser Algorithmus anhand eines illustrierten Beispiels viel mehr Sinn ergibt. Da es sich bei Heaps um eine Art Baum handelt, ist es hilfreich, sie zu visualisieren, so wie wir es bei Binärbäumen tun. Also machen wir das jetzt gleich!
Hast du schon einmal unter die Haube von Heap Sort geschaut?
Ja, es ist Zeit für meinen absoluten Lieblingsteil beim Lernen von Heap Sort: das Zeichnen! Hurra! Um zu verstehen, was unter der Haube von Heap-Sort vor sich geht, werden wir mit einem kleinen, unsortierten Datensatz arbeiten.
Leave a Reply