6 Partiell geordnete binäre Bäume: Heap (Haufen) Motivation für manchen Anwendungen nur partielle Ordnung der Elemente statt vollständiger nötig, z.b. - Prioritätsschlange: nur das minimale (oder maximale) Element - k Maximalwerte aus Menge mit n >> k Elementen (Rangfolgebestimmung von Suchmaschinen!) Die typische Operationen: enqueue() findmin() dequeuemin() Gesucht Datenstruktur, die alle Operationen auch im schlechtesten Fall in logarithmischer Zeit O(log n) ausführt Verschiedene Realisierungen, hier binärer Heap Achtung, nicht mit "Freispeicher-Halde" ("heap")verwechseln!! hs / fub alp--heap Heap () Partiell geordneter Baum ist ein knotenmarkierter Binärbaum mit der Eigenschaft: jeder Knotenwert ist kleiner oder gleich den Werten seiner Nachfolger (Heap-Invariante): für alle Knoten k: c e child(k) => k.val( ) <=c.val( ) 9 Operationen: Einfügen enqueue() Minimum entfernen dequeuemin() evtl. findmin() 8 0 "MaxHeap": k.val() >= c.val() analog. hs / fub alp--heap
Binärer Heap Logarithmische Laufzeit? Kann Baum entarten? 9 JA 5 6 0 5 Ziel: Baum möglichst ausgeglichen halten z.b. Binominal Heap, Fibonacci Heap hier: Binärer Heap hs / fub alp--heap Binärer Heap Zusätzliche Strukturinvariante: Fast vollständiger binärer Baum 5 6 h 5 9 0 6 5 8 Höhe h : h <= n < h+ => h <= log n Einige Beispiele aus Goodrich/ Tamassia (s. Lit.-Liste) hs / fub alp--heap
Beispiel Kein binärer Heap 5 6 5 0 6 5 8 hs / fub alp--heap 5 Binäre Heaps Kein binärer Heap 5 6 5 9 0 6 5 8 hs / fub alp--heap 6
Binärer Heap Einfügen (enqueue) 9 8 5 0 8 9 8 0 (i) vollständiger Baum => Knoten hier einfügen (ii) Heap-Eigenschaft wiederherstellen hs / fub alp--heap Binärer Heap enqueue() 9 8 5 0 8 8 9 0 while (parent > val) {exchange();} ("upheap") O(log n) Vertauschungen hs / fub alp--heap 8
Binärer Heap Vollständiger Baum: Feldrepräsentation 9 8 5 0 8 8 9 0 9 8 0 8 0 5 8 9 0... 5 Reguläre Struktur: Nachfolger des Knoten i sind die Knoten *i und *i+, Vorgänger von i : i/ hs / fub alp--heap 9 Imperative Implementierung public class VectorHeap implements... { // model: // data Ord t => POTree t = E N(POTree t) t (POTree t) // inv E = True // inv(n l x r) = (if l /= E then x<=root l else True) && (if r /= E then x<=root r else True) && inv l && inv r // && and POTree is complete. Object [] vheap; // the array implementing the tree private int size; //number of nodes private int length; //a.length private int current; // the current node private final int ROOT = ; // the root hs / fub alp--heap 0 5
Binary heap: enqueue public void enqueue(comparable val) throws java.lang.exception { // requires : - // effects: inserts val into this as a leaf into the // only possible position which maintains completeness // of tree and maintains heap invariant // if count > size throws an execption if (sizet== vheap.length -) throw new java.lang.exception("heap full"); size++; int i = size; while (i > && vheap[parent(i)].compareto(val)>0) { vheap[i] = vheap[parent(i)]; i = i/; } vheap[i] = val; } hs / fub alp--heap Binärer Heap: dequeue dequeue 9 8 5 0 Minimum entfernen. ) Inv. "fast vollständig" herstellen: -> letztes Element als Wurzel. ) Heap-Invariante herstellen. 8 9 0 8 muss hier entfernt (Vollständigkeit) und passend eingefügt werden (Heap-Eigenschaft) hs / fub alp--heap 6
Beispiel: dequeue 8 9 8 5 0 8 9 0 hs / fub alp--heap Beispiel: dequeue 8 9 solange ein Kind mit kleinerem Wert existiert: Tausche mit kleinerem der Kinder. 8 5 0 8 9 0 hs / fub alp--heap
"downheap" 9 8 5 8 0 8 9 0 hs / fub alp--heap 5 Beispiel 9 8 5 0 8 8 9 0 hs / fub alp--heap 6 8
Binärer Heap: dequeue Noch ein Beispiel 6 5 5 0 8 0 9 0 hs / fub alp--heap 5 6 0 5 0 8 9 0 Tauschoperationen: 0 <->, <-> 0, 5 <-> 0 hs / fub alp--heap 8 9
Binärer Heap Laufzeit: enqueue() und dequeue(): O(log n) findmin() : O() Sortieren mit Heap: n*log n Operationen. Konstruktion eines Heap: n log n Schritte. Geht das bessser? Ja hs / fub alp--heap 9 Konstruktion eine Heap mit n = k Elementen (n+)/ Elemente zu Heap-Knoten machen. hs / fub alp--heap 0 0
n+ / Elemente hinzunehmen zu n-/ heaps verschmelzen. Heap-Eigenschaft herstellen (downheap) ) enqueue(9) ) enqueue(8) enqueue ()
Heap-Konstruktion "Bottom-up"-Konstruktion benötigt O(n) Schritte. (n+)/ Knoten einfügen (n+)/ Knoten einfügen und downheap (n+)/8 Knoten einfügen und downheap... n Einfügeoperationen, n/ upheaps => O(n) hs / fub alp--heap