Zum Hauptinhalt springen

BinaryHeap

Eine generische binäre Heap-Implementierung, die sowohl MinHeap- als auch MaxHeap-Varianten mit effizienten prioritätsbasierten Operationen bereitstellt.

Installation

npm install @msnkr/data-structures

Verwendung

import { MinHeap, MaxHeap } from '@msnkr/data-structures';

const minHeap = new MinHeap<number>();
const maxHeap = new MaxHeap<number>();

API-Referenz

Eigenschaften

  • size: number - Anzahl der Elemente im Heap
  • isEmpty(): boolean - Ob der Heap leer ist

Methoden

Grundlegende Operationen

// Element einfügen - O(log n)
heap.insert(5);

// Wurzelelement entfernen - O(log n)
const root = heap.remove();

// Wurzelelement ansehen - O(1)
const top = heap.peek();
Performance

Einfüge- und Entfernoperationen sind O(log n), mit O(1) Zugriff auf das minimale (MinHeap) oder maximale (MaxHeap) Element.

Suche und Hilfsfunktionen

// Prüfen, ob Element existiert - O(n)
const exists = heap.contains(42);

// Alle Elemente entfernen - O(1)
heap.clear();

// In Array konvertieren (Level-Order) - O(n)
const array = heap.toArray();

Iteration

// Level-Order-Traversierung
for (const value of heap) {
console.log(value);
}

Beispiele

MinHeap-Verwendung

const minHeap = new MinHeap<number>();

// Elemente einfügen
minHeap.insert(5);
minHeap.insert(3);
minHeap.insert(7);
minHeap.insert(1);

console.log(minHeap.peek()); // 1 (minimales Element)
console.log(minHeap.remove()); // 1
console.log(minHeap.peek()); // 3 (neues Minimum)
console.log(minHeap.size); // 3

MaxHeap-Verwendung

const maxHeap = new MaxHeap<number>();

// Elemente einfügen
maxHeap.insert(5);
maxHeap.insert(3);
maxHeap.insert(7);
maxHeap.insert(10);

console.log(maxHeap.peek()); // 10 (maximales Element)
console.log(maxHeap.remove()); // 10
console.log(maxHeap.peek()); // 7 (neues Maximum)

Effiziente Heap-Konstruktion

// Heap aus Array erstellen - O(n)
const minHeap = new MinHeap<number>(null, [5, 3, 8, 1, 7, 4]);
console.log(minHeap.peek()); // 1 (minimales Element)
console.log(minHeap.size); // 6

// Ebenso für MaxHeap
const maxHeap = new MaxHeap<number>(null, [5, 3, 8, 1, 7]);
console.log(maxHeap.peek()); // 8 (maximales Element)
console.log(maxHeap.size); // 5
Effiziente Initialisierung

Der Aufbau eines Heaps aus einem Array verwendet einen O(n) Heapify-Algorithmus, der deutlich schneller ist als das Einfügen von Elementen einzeln (O(n log n)).

Benutzerdefinierter Komparator für Objekte

interface Person {
name: string;
age: number;
}

// Min-Heap nach Alter
const byAge = (a: Person, b: Person) => a.age - b.age;
const minHeap = new MinHeap<Person>(byAge);

minHeap.insert({ name: 'Alice', age: 25 });
minHeap.insert({ name: 'Bob', age: 20 });
minHeap.insert({ name: 'Charlie', age: 30 });

console.log(minHeap.peek()); // { name: "Bob", age: 20 }

K größte Elemente finden

function findKLargest(arr: number[], k: number): number[] {
const minHeap = new MinHeap<number>();

for (const num of arr) {
minHeap.insert(num);
if (minHeap.size > k) {
minHeap.remove(); // Kleinstes entfernen
}
}

return minHeap.toArray().sort((a, b) => b - a);
}

const numbers = [3, 1, 5, 12, 2, 11, 9, 7];
console.log(findKLargest(numbers, 3)); // [12, 11, 9]

Median-Finder

class MedianFinder {
private maxHeap = new MaxHeap<number>(); // Untere Hälfte
private minHeap = new MinHeap<number>(); // Obere Hälfte

addNum(num: number): void {
// Zuerst zum Max-Heap hinzufügen (untere Hälfte)
this.maxHeap.insert(num);

// Ausgleichen: Größtes von unten nach oben verschieben
this.minHeap.insert(this.maxHeap.remove());

// Größen ausgleichen: maxHeap sollte gleich viele oder 1 Element mehr haben
if (this.maxHeap.size < this.minHeap.size) {
this.maxHeap.insert(this.minHeap.remove());
}
}

findMedian(): number {
if (this.maxHeap.size > this.minHeap.size) {
return this.maxHeap.peek();
}
return (this.maxHeap.peek() + this.minHeap.peek()) / 2;
}
}

const mf = new MedianFinder();
mf.addNum(1);
mf.addNum(2);
console.log(mf.findMedian()); // 1.5
mf.addNum(3);
console.log(mf.findMedian()); // 2

Fehlerbehandlung

import { EmptyStructureError } from '@msnkr/data-structures';

try {
const empty = new MinHeap<number>();
empty.remove(); // Wirft EmptyStructureError
} catch (error) {
if (error instanceof EmptyStructureError) {
console.log('Heap is empty!');
}
}

try {
const empty = new MaxHeap<number>();
empty.peek(); // Wirft EmptyStructureError
} catch (error) {
if (error instanceof EmptyStructureError) {
console.log('Cannot peek at empty heap!');
}
}
Leerer Heap

remove() und peek() werfen EmptyStructureError, wenn sie auf einem leeren Heap aufgerufen werden.

Leistungsmerkmale

OperationZeitkomplexitätBeschreibung
insert()O(log n)Element zum Heap hinzufügen
remove()O(log n)Wurzelelement entfernen
peek()O(1)Wurzelelement ansehen
contains()O(n)Nach Element suchen
toArray()O(n)In Array konvertieren
clear()O(1)Alle Elemente entfernen
KonstruktionO(n)Heap aus Array aufbauen

Platzkomplexität: O(n), wobei n die Anzahl der Elemente ist

Implementierungsdetails

Array-basierte Speicherung

Der Heap wird als vollständiger Binärbaum in einem Array gespeichert. Für jeden Knoten am Index i:

  • Linkes Kind: 2i + 1
  • Rechtes Kind: 2i + 2
  • Elternteil: ⌊(i - 1) / 2⌋
       1
/ \
3 2
/ \
5 4

Array: [1, 3, 2, 5, 4]
Indizes: 0 1 2 3 4

Heap-Eigenschaft

MinHeap: Elternteil ≤ Kinder (Wurzel ist Minimum) MaxHeap: Elternteil ≥ Kinder (Wurzel ist Maximum)

Heapify-Algorithmus

Bei der Initialisierung mit einem Array verwendet der Heap den Heapify-Algorithmus von Floyd:

  • Beginnt beim letzten Nicht-Blatt-Knoten
  • Arbeitet rückwärts und "siftet" jeden Knoten nach unten
  • Zeitkomplexität: O(n) - effizienter als n Einfügungen (O(n log n))
Wann BinaryHeap verwenden

Perfekt für:

  • Effizientes Finden von Min/Max-Elementen
  • Priority-Queue-Implementierungen
  • K größte/kleinste Elemente Probleme
  • Heapsort-Algorithmus
  • Median-Findung (Zwei-Heap-Ansatz)
  • Streaming-Daten mit Top-k-Abfragen
MinHeap vs MaxHeap

Wählen Sie basierend auf Ihren Anforderungen:

  • MinHeap: Schneller Zugriff auf minimales Element
  • MaxHeap: Schneller Zugriff auf maximales Element
  • Kann Min und Max nicht gleichzeitig effizient abrufen

Vergleich mit PriorityQueue

MerkmalBinaryHeapPriorityQueue
APIinsert(), remove()enqueue(), dequeue()
AnwendungsfallLow-Level-Heap-OperationenQueue-ähnliche Prioritätsbehandlung
AbstraktionDirekte Heap-ManipulationHöherstufige Queue-Schnittstelle
Welches verwenden?
  • Verwenden Sie PriorityQueue für Aufgabenplanung, Ereigniswarteschlangen (Queue-Semantik)
  • Verwenden Sie BinaryHeap für Algorithmen, die direkte Heap-Operationen erfordern (Heapsort usw.)

Siehe auch

  • PriorityQueue - Höherstufige Priority-Queue auf Heap-Basis
  • Queue - First-In-First-Out (FIFO) Warteschlange