Ein Heap ist ein vollständiger Binärbaum, in dem jedes übergeordnete Element die Heap-Eigenschaft erfüllt – entweder immer kleiner (Min.-Heap) oder immer größer (Max-Heap) als seine untergeordneten Elemente. „Abgeschlossen“ bedeutet, dass jedes Level voll ist, mit Ausnahme möglicherweise des letzten, das von links nach rechts gefüllt wird.
1 Min-heap
/ \
3 5
/ \
7 4
Da es vollständig ist, speichern wir es in einem flachen Array – es sind keine Zeiger erforderlich. Für Index i: linkes Kind = 2i + 1, rechtes Kind = 2i + 2, Eltern = (i - 1) // 2.
| Eigentum | Min-Heap | Max-Heap | |----------|----------|----------| | Wurzel | Kleinstes Element | Größtes Element | | Eltern ≤ Kinder? | ✅ Ja | ❌ Nein (≥) | | Auszug ergibt | Minimum | Maximal |
Pythons heapq ist standardmäßig ein Min-Heap. Negieren Sie für einen Max-Heap Werte beim Einfügen und erneut beim Extrahieren.
Einfügen – bis zum Ende drücken, dann aufblasen (mit dem übergeordneten Element tauschen, solange es kleiner ist):
import heapq
h = [1, 3, 5, 7]
heapq.heappush(h, 2) # h becomes [1, 2, 5, 7, 3]
Mindestmenge extrahieren – Wurzel mit letztem Element tauschen, letztes einfügen, dann nach unten sieben (mit kleinerem Kind tauschen):
smallest = heapq.heappop(h) # returns 1
Beide Operationen werden in O(log n) ausgeführt, da die Baumhöhe log n ist.
Anmelden an der Diskussion teilnehmen
Der Aufruf von heapq.heapify(arr) konvertiert eine Liste in-place in einen Heap in O(n), nicht in O(n log n). Es funktioniert von unten nach oben und durchsucht jeden Nicht-Blattknoten. Dies ist eines der überraschendsten Komplexitätsergebnisse in CS.
Mit einer Prioritätswarteschlange können Sie immer zuerst auf das Element mit der höchsten Priorität zugreifen. Heaps sind die bevorzugte Implementierung, da sowohl Einfügen als auch Extrahieren O(log n) sind. Verwenden Sie eines immer dann, wenn Sie „Geben Sie mir den bisher besten Artikel“ benötigen.
„Finden Sie die K größten Elemente in einem unsortierten Array.“
Behalten Sie einen Min-Heap der Größe K. Drücken Sie für jedes Element darauf; Wenn der Heap größer als K ist, platziere den kleinsten. Übrig bleiben die K-größten.
import heapq
def top_k(nums, k):
return heapq.nlargest(k, nums)
Zeit: O(n log k) – viel besser als Sortieren, wenn k ≪ n.
Sie benötigen die 5 höchsten Punktzahlen aus 1 Million Einträgen. Welcher Heap-Typ und welche Größe?
Schieben Sie den Kopf jeder Liste in einen Min-Heap. Platzieren Sie das kleinste Element und verschieben Sie dann das nächste Element aus derselben Liste. Wiederholen, bis alle Listen erschöpft sind. Zeit: O(N log K) wobei N die Gesamtzahl der Elemente ist.
Behalten Sie zwei Heaps bei: einen Max-Heap für die untere Hälfte und einen Min-Heap für die obere Hälfte. Gleichen Sie ihre Größen so aus, dass sie sich höchstens um 1 unterscheiden. Der Median liegt immer bei einer oder beiden Wurzeln.
Lower half (max-heap): [1, 2, 3] ← max = 3
Upper half (min-heap): [4, 5, 6] ← min = 4
Median = (3 + 4) / 2 = 3.5
Wo landet beim Zwei-Heap-Median-Ansatz ein neues Element zuerst?
Bei der Planung glänzen jede Menge Dinge: Besprechungsräume (verfolgen Sie die früheste Endzeit), Aufgabenplanung mit Abklingzeiten oder CPU-Jobwarteschlangen. Die wichtigste Erkenntnis besteht darin, dass ein Heap effizient verfolgt, „was als nächstes endet“.
| Brauchen | Beste Wahl | Warum | |------|-------------|-----| | Wiederholte Min/Max-Extraktion | Haufen | O(log n) einfügen + extrahieren | | Statische Daten, einmalige Sortierung | Sortiertes Array | O(n log n) einmal, O(1) Zugriff | | Bereichsabfragen + Bestellstatistiken | Ausgewogener BST | O(log n) für alles | | Top-K aus einem Stream | Haufen der Größe K | O(n log k) insgesamt |
Welche Operation ist O(1) in einem Min-Heap?
| Betrieb | Zeit | |-----------|------| | Einfügen | O(log n) | | Extrahieren Sie Min./Max. | O(log n) | | Peek min/max | O(1) | | Aufhäufen | O(n) | | Top-K aus n Elementen | O(n log k) |