Heap-Sort-Algorithmus (mit Code in Python und C++)
โก Intelligente Zusammenfassung
Der Heap-Sort-Algorithmus sortiert ein Array, indem er einen binรคren Heap erstellt und diesen wiederholt durchlรคuft.tracDer Wurzelwert wird in den sortierten Bereich eingefรผgt. Diese Ressource erklรคrt Heapify, Max- und Min-Heaps, Pseudocode und die vollstรคndige Implementierung. Python und C++ Implementierungen mit Zeitkomplexitรคtsanalyse.

Was ist ein Heap-Sortieralgorithmus?
Heapsort ist einer der beliebtesten und schnellsten Sortieralgorithmen. Er basiert auf der Datenstruktur eines vollstรคndigen Binรคrbaums. Wir suchen das grรถรte Element und fรผgen es oben im Heap, dem Elternknoten des Binรคrbaums, ein.
Nehmen wir an, ein Array sei gegeben, Daten = [10,5, 7, 9, 4, 11, 45, 17, 60].
Wenn im Array der i-te Index (i=0,1,2,3 โฆ) ein รผbergeordneter Knoten ist, sind (2i+1) und (2i+2) die linken und rechten untergeordneten Knoten. Das Erstellen eines vollstรคndigen Binรคrbaums mit diesem Array sieht folgendermaรen aus:
Wir fรผhren den Heapify-Prozess vom Anfang bis zum Ende des Arrays durch. Wenn wir das Array zunรคchst in einen Baum umwandeln, sieht es wie oben aus. Wir kรถnnen sehen, dass es keine Heap-Eigenschaft (Min-Heap oder Max-Heap) beibehรคlt. Wir erhalten das sortierte Array, indem wir den Heapify-Prozess fรผr alle Knoten durchfรผhren.
Anwendung der Heap-Sortierung
Hier ist eine Verwendung des Heap-Sortieralgorithmus:
- Der Aufbau von โPrioritรคtswarteschlangenโ erfordert eine Heap-Sortierung. Weil Heapsort das Element nach jedem Einfรผgen sortiert hรคlt.
- Die Heap-Datenstruktur ist effizient beim Finden des kth grรถรtes Element in einem bestimmten Array.
- Der Linux-Kernel verwendet standardmรครig die Heap-Sortierung Sortieralgorithmus da es eine Speicherkomplexitรคt von O (1) hat.
Erstellen Sie eine Heap-Sortierung anhand eines Beispiels
Hier werden wir einen maximalen Heap aus dem folgenden vollstรคndigen Binรคrbaum konstruieren.
Die Blattknoten sind 17, 60, 4, 11 und 45. Sie haben keine untergeordneten Knoten. Deshalb sind sie Blattknoten. Daher starten wir die Heapify-Methode von ihrem รผbergeordneten Knoten aus. Hier sind die Schritte:
Schritt 1) Wรคhlen Sie den Unterbaum ganz links aus. Wenn die untergeordneten Knoten grรถรer sind, tauschen Sie den รผbergeordneten Knoten mit dem untergeordneten Knoten aus.
Hier ist der รผbergeordnete Knoten 9. Und die untergeordneten Knoten sind 17 und 60. Da 60 der grรถรte ist, werden 60 und 9 vertauscht, um die beizubehalten max Haufen.
Schritt 2) Jetzt wird der am weitesten links stehende Teilbaum gehรคuft. Der nรคchste รผbergeordnete Knoten ist 7. Dieser รผbergeordnete Knoten hat zwei untergeordnete Knoten, und der grรถรte ist 45. Daher werden 45 und 7 vertauscht.
Schritt 3) Die Knoten 60 und 4 haben den รผbergeordneten Knoten 5. Da โ5โ kleiner als der untergeordnete Knoten 60 ist, wird er vertauscht.
Schritt 4) Jetzt hat Knoten 5 den untergeordneten Knoten 17,9. Dadurch wird die Max-Heap-Eigenschaft nicht beibehalten. Also wird 5 durch 17 ersetzt.
Schritt 5) Knoten 10 wird mit 60 und dann mit 17 ausgetauscht. Der Vorgang sieht wie folgt aus.
Schritt 6) Bis Schritt 5 haben wir den maximalen Heap erstellt. Jeder รผbergeordnete Knoten ist grรถรer als seine untergeordneten Knoten. Der Wurzelknoten hat den Maximalwert (60).
Hinweis: Um das sortierte Array zu erstellen, mรผssen wir den Knoten mit dem hรถchsten Wert durch seinen Nachfolger ersetzen.
Dieser Vorgang heiรt โextract maxโ. Da 60 der maximale Knoten ist, legen wir seine Position auf den 0. Index fest und erstellen den Heap ohne Knoten 60.
Schritt 7) Wenn 60 entfernt wird, ist der nรคchste Maximalwert 45. Wir werden den Prozess โExโ durchfรผhren.tract Maxโ erneut von Knoten 45.
Diesmal erhalten wir 45 und ersetzen den Wurzelknoten durch seinen Nachfolger 17.
Wir mรผssen Leistung erbringenโExtract Maxโ bis alle Elemente sortiert sind.
Nachdem wir diese Schritte bis zum Ende durchgefรผhrt habentracDurch die Addition aller Maximalwerte erhalten wir das folgende Array.
Was ist ein binรคrer Heap?
Ein binรคrer Heap ist eine Art vollstรคndiger binรคrer Baum Datenstruktur. In einer solchen Baumstruktur ist der รผbergeordnete Knoten entweder grรถรer oder kleiner als die untergeordneten Knoten. Wenn der รผbergeordnete Knoten kleiner ist, wird der Heap โMin Heapโ genannt, und wenn der รผbergeordnete Knoten grรถรer ist, wird der Heap โMax Heapโ genannt.
Hier sind Beispiele fรผr Min Heap und Max Heap.

Wenn Sie in der obigen Abbildung den โMin Heapโ bemerken, ist der รผbergeordnete Knoten immer kleiner als seine untergeordneten Knoten. An der Spitze des Baumes finden wir den kleinsten Wert 10.
Ebenso ist beim โMax Heapโ der รผbergeordnete Knoten immer grรถรer als die untergeordneten Knoten. Das maximale Element ist am Kopfknoten fรผr den โMax Heapโ vorhanden.
Was ist โHeapifyโ?
โHeapifyโ ist das Prinzip des Heaps, das die Position des Knotens sicherstellt. Bei Heapify behรคlt ein Max-Heap immer eine Beziehung zwischen รผbergeordnetem und untergeordnetem Knoten bei, d. h. der รผbergeordnete Knoten ist grรถรer als die untergeordneten Knoten.
Wird beispielsweise ein neuer Knoten hinzugefรผgt, muss der Heap umgeformt werden. Dabei kann es jedoch erforderlich sein, Knoten zu รคndern oder zu vertauschen oder das Array neu anzuordnen. Dieser Umformungsprozessping Ein solcher Haufen wird als โHeapifyโ bezeichnet.
Hier ist ein Beispiel, wie Heapify funktioniert:

Hier sind die Schritte fรผr Heapify:
Schritt 1) Knoten 65 als rechtes untergeordnetes Element von Knoten 60 hinzugefรผgt.
Schritt 2) รberprรผfen Sie, ob der neu hinzugefรผgte Knoten grรถรer als der รผbergeordnete Knoten ist.
Schritt 3) Da er grรถรer als der รผbergeordnete Knoten ist, haben wir den rechten untergeordneten Knoten mit seinem รผbergeordneten Knoten vertauscht.
So erstellen Sie den Heap
Bevor wir den Heap erstellen oder einen Baum heapifizieren, mรผssen wir wissen, wie wir ihn speichern werden. Da der Heap ein vollstรคndiger binรคrer Baum ist, ist es besser, einen Array um die Daten des Heaps zu speichern.
Nehmen wir an, ein Array enthรคlt insgesamt n Elemente. Wenn der โiโ-te Index ein รผbergeordneter Knoten ist, befindet sich der linke Knoten am Index (2i+1), und der rechte Knoten befindet sich am Index (2i+2). Wir gehen davon aus, dass der Array-Index bei 0 beginnt.
Lassen Sie uns damit einen maximalen Heap in einem Array wie folgt speichern:

Der Heapify-Algorithmus behรคlt die Heap-Eigenschaft bei. Wenn der รผbergeordnete Knoten nicht den Extremwert (kleiner oder grรถรer) hat, wird er mit dem extremsten untergeordneten Knoten ausgetauscht.
So heben Sie einen maximalen Heap auf:
Schritt 1) Beginnen Sie am Blattknoten.
Schritt 2) Finden Sie das Maximum zwischen Eltern und Kindern.
Schritt 3) Tauschen Sie die Knoten aus, wenn der untergeordnete Knoten einen grรถรeren Wert hat als der รผbergeordnete.
Schritt 4) Gehen Sie eine Ebene hรถher.
Schritt 5) Befolgen Sie die Schritte 2,3,4, bis wir den Index 0 erreichen, oder sortieren Sie den gesamten Baum.
Hier ist der Pseudocode fรผr rekursives Heapify (max heap):
def heapify(): inputโ array, size, i largest = i left = 2*i + 1 right = 2*i + 2 if left<n and array[largest ] < array[left]: largest = left if right<n and array[largest ] < array[right]: largest = right If largest not equals i: swap(array[i],array[largest]) heapify(array,n,largest)
Spitzname Code fรผr Heapsort
Hier ist der Pseudocode fรผr den Heap-Sortieralgorithmus:
Heapify(numbers as an array, n as integer, i as integer): largest = i left = 2i+1 right= 2i+2 if(left<=n) and (numbers[i]<numbers[left]) largest=left if(right<=n) and (numbers[i]<numbers[right]) largest=right if(largest != i) swap(numbers[i], numbers[largest]) Heapify(numbers,n,largest) HeapSort(numbers as an array): n= numbers.size() for i in range n/2 to 1 Heapify(numbers,n,i) for i in range n to 2 Swap numbers[i] with numbers[1] Heapify(numbers,i,0)
Beispiel fรผr Heapsortierung Code in C++
#include <iostream> using namespace std; void display(int arr[], int n) { for (int i = 0; i < n; i++) { cout << arr[i] << "\t"; } cout << endl; } void heapify(int numbers[], int n, int i) { int largest = i; int left = 2 * i + 1; int right = 2 * i + 2; if (left < n && numbers[left] < numbers[largest]) { largest = left; } if (right < n && numbers[right] < numbers[largest]) { largest = right; } if (largest != i) { //uncomment the following line to see details in output //cout<<"Swapping "<< numbers[i]<< " and "<<numbers[largest]<<endl; swap(numbers[i], numbers[largest]); heapify(numbers, n, largest); } } void heapSort(int numbers[], int n) { for (int i = n/2 - 1; i >= 0; i--) { heapify(numbers, n, i); //uncomment the following line to see details in output //cout<<"Heapify:\t"; //display(numbers,n); } for (int i = n - 1; i >= 0; i--) { swap(numbers[0], numbers[i]); heapify(numbers, i, 0); } } int main() { int numbers[] = { 10,5, 7, 9, 4, 11, 45, 17, 60}; int size = sizeof(numbers) / sizeof(numbers[0]); cout<<"Initial Array:\t"; display(numbers,size); heapSort(numbers, size); cout<<"Sorted Array (descending order):\t"; display(numbers, size); }
Ausgang:
Initial Array: 10 5 7 9 4 11 45 17 60 Sorted Array (descending order): 60 45 17 11 10 9 7 5 4
Beispiel fรผr Heapsortierung Code in Python
def display(arr): for i in range(len(arr)): print(arr[i], end = "\t") print() def heapify(numbers, n, i): largest = i left = 2 * i + 1 right = 2 * i + 2 if left < n and numbers[left] < numbers[largest]: largest = left if right < n and numbers[right] < numbers[largest]: largest = right if largest != i: numbers[i], numbers[largest] = numbers[largest], numbers[i] heapify(numbers, n, largest) def heapSort(items, n): for i in range(n //2,-1,-1): heapify(items, n, i) for i in range(n - 1, -1, -1): items[0], items[i] = items[i], items[0] heapify(items, i, 0) numbers = [10, 5, 7, 9, 4, 11, 45, 17, 60] print("Initial List:\t", end = "") display(numbers) print("After HeapSort:\t", end = "") heapSort(numbers, len(numbers)) display(numbers)
Ausgang:
Initial List: 10 5 7 9 4 11 45 17 60 After HeapSort: 60 45 17 11 10 9 7 5 4
Zeitliche und rรคumliche Komplexitรคtsanalyse von Heap Sort
Es gibt Zeitkomplexitรคt und Raumkomplexitรคt, die wir fรผr die Heapsortierung analysieren kรถnnen. Fรผr die Zeitkomplexitรคt gibt es die folgenden Fรคlle:
- besten Case
- Durchschnittlicher Fall
- Schlimmsten Fall
Der Heap wird auf einem vollstรคndigen Binรคrbaum implementiert. Auf der untersten Ebene des Binรคrbaums befindet sich also die maximale Anzahl an Knoten. Wenn die unterste Ebene n Knoten hat, dann hat die obere Ebene n/2 Knoten.
In diesem Beispiel verfรผgt Ebene 3 รผber vier Elemente, Ebene 2 รผber zwei Elemente und Ebene 1 รผber ein Element. Wenn insgesamt n Elemente vorhanden sind, wird die Hรถhe bzw. das Gesamtniveau angegeben Log2(N). Das Einfรผgen eines einzelnen Elements kรถnnte also maximal Log(n)-Iterationen erfordern.
Wenn wir den maximalen Wert aus dem Heap nehmen wollen, nehmen wir einfach den Stammknoten. Dann fรผhren wir erneut das Heapify aus. Jedes Heapify nimmt Log2(n) Zeit. BeispieltracDas Erreichen des Maximums benรถtigt O(1) Zeit.
Bester Fall der Zeitkomplexitรคt fรผr den Heapsort-Algorithmus
Wenn alle Elemente bereits im Array sortiert sind, dauert der Aufbau des Heaps O(n) Zeit. Denn wenn die Liste sortiert ist, dauert das Einfรผgen eines Elements die konstante Zeit O(1).
Daher wird es im besten Fall O(n) Zeit dauern, einen Max-Heap oder Min-Heap zu erstellen.
Durchschnittliche Fallzeitkomplexitรคt fรผr den Heapsort-Algorithmus
Einfรผgen eines Elements oder BeispielstracDas Finden eines Maximums kostet O(log(n)) Zeit. Die durchschnittliche Zeitkomplexitรคt des Heapsort-Algorithmus betrรคgt also O(n log(n)).
Worst-Case-Zeitkomplexitรคt fรผr den Heapsort-Algorithmus
รhnlich wie im durchschnittlichen Fall mรผssen wir im schlimmsten Fall Heapify n-mal durchfรผhren. Jedes Heapify kostet O(log(n)) Zeit. Die Zeitkomplexitรคt im schlimmsten Fall betrรคgt also O(n log(n)).
Speicherkomplexitรคt fรผr den Heapsort-Algorithmus
Heapsort ist ein direkt entwickelter Algorithmus. Das bedeutet, dass kein zusรคtzlicher oder temporรคrer Speicher benรถtigt wird, um die Aufgabe auszufรผhren. Wenn wir uns die Implementierung ansehen, werden wir feststellen, dass wir swap() verwendet haben, um den Austausch der Knoten durchzufรผhren. Es wurde keine andere Liste oder kein anderes Array benรถtigt. Die Speicherkomplexitรคt betrรคgt also O(1).














