6 Halde (Heap) Die Halde ist eine lineares Feld, welches die sogenannte Haldenbedinung erfüllt: Haldenbedingung: A[i]≥ max {A[2i], A[2i + 1]}, ∀i = 1, 2, . . . n 2 . Direkt aus der Denition ergibt sich, dass A[1] das Maximum des linearen Feldes ist. Beispiel einer Halde: Die Halde lässt sich auch als binärer Baum darstellen. Mit den Funktionen LINKS(i) und RECHTS(i) kann auf den linken bzw. rechten Nachfolger des i-ten Elements in der Baumstruktur zugegrien werden, analog mit VATER(i) auf den Vorgänger. LINKS (i) 1: RETURN 2i RECHTS(i) 1: RETURN 2i + 1 VATER (i) 1: RETURN 2i Wichtige Beobachtungen: • Das Maximum sitzt in der Wurzel des Baums • In jedem Knoten ist die Haldenbedingung erfüllt • Die Maximale Tiefe des Baums ist blog nc • In einem Teilbaum sind alle darunter liegenden Knoten kleiner oder ma- ximal gleich groÿ. 1 In jedem Haldenbaum ist jedes Niveau bis auf das letzte voll (es gibt 2i Elemente der Höhe i), das letzte Niveau enthält mindestens 1 Element. Für die Anzahl der Elemente in einem Haldenbaum der Höhe h gilt also Beweis für die Höhe des Haldenbaums: n ≥ 1 + 2 + 4 + . . . + 2h−1 + 1 = h−1 X 2i + 1 = (2h − 1) + 1 = 2h , i=1 Für die Höhe h gilt daher h ≤ bldnc (h ganzzahlig). 6.1 Verhalden (Heapify) Verhalden ist der zentrale Prozess für alle Anwendungen der Haldenstruktur. Mit n als Gröÿe der Halde (Die Länge des linaren Feldes). VERHALDE (A,i) 1: l←LINKS(i), r←RECHTS(i) 2: index ← i 3: IF l≤n AND A[l]>A[i] THEN index←l 4: IF r≤n AND A[r]>A[index] THEN index←r 5: IF i6=index THEN 6: VERTAUSCHE (A[i], A[index]) 7: VERHALDE (A,index) : Der rekursive Aufruf erfolgt auf einem Teilbaum, der einen der beiden Söhne von i als Wurzel hat. Dieser Teilbaum hat maximal halb so viele Elemente wie der Teilbaum mit Wurzel i. Die Rekursiongleichung lautet daher T (n) ≤ O(1) + T ( n2 ). Die Lösung ist T (n) = O(log n): Analyse n T (n) ≤ O(1) + T ( ) h 2 n i ≤ O(1) + O(1) + T ( ) 4 n = 2 · O(1) + T ( ) 4 n ≤ 3 · O(1) + T ( ) 8 n ≤ k · O(1) + T ( k ) 2 = ldn · O(1) + O(1) = O(log n) Diese Schranke folgt auch aus der Beobachtung, dass maximal die Höhe des Haldenbaums, h ≤ bldnc, durchlaufen wird. 6.2 Aufbau einer Halde Eine Halde kann aus einem beliebigen linearen Feld A aufgebaut werden: 2 BAUE_HALDE (A) 1: FOR i←n/2 DOWNTO 1 2: VERHALDE (A,i) : Das Verhalden wird n2 -mal durchgeführt. D.h. T (n) = O(n·log n). Bei genauerer Betrachtung sieht man aber, dass eben nicht alle Elemente durch die ganze Baumhöhe durch verhaldet werden müssen. Die Schranke O(n · log n) ist nicht scharf. Ein genauerer Ansatz ergibt sich aus der Beobachtung, dass es in einer Halde n mit n Elementen ≤ d 2h+1 e Elemente gibt, die mit Höhe h verhaldet werden Pbldnc n P h müssen: T (n) ≤ h=0 d 2h+1 eO(h) = O(n bldnc ) = O(n) . h=0 2h P h (Die Summe kann durch eine unendliche Summe ∞ h=0 2h = 2 abgeschätzt werden.) Analyse Damit kann eine Halde in linearer Zeit aus einem linearen Feld gebaut werden. 6.3 Sortieren mit Halden (Heap Sort) Mit Hilfe des VERHALDE -Algorithmus kann man auch einen Sortieralgoritmus konstruieren. HEAP_SORT(A) 1: BAUE_HALDE(A) 2: FOR i ← n DOWNTO 2 DO 3: VERTAUSCHE (A[1],A[i]) 4: n ← n-1 5: VERHALDE (A,1) Die Laufzeit von BAUE_HALDE ist O(n), die von VERHALDE O(log n). Die Laufzeit beträgt daher T (n) = O(n) + (n − 1) · O(log n) = O(n log n). Der Algorithmus arbeitet in-place. 6.4 Wartschlange (Priority Queue) Eine weitere Anwendung dieser Datenstruktur ist die Warteschlange mit Prioritäten: Eine Warteschlange liegt vor, wenn folgende drei Operationen durchgeführt werden können: • EINFUEGEN (A,x) • MAX (A) • ENTFERNE_MAX (A) Die Funktionen mit Hilfe einer Halde umgesetzt in Pseudocode: MAXIMUM (A) 1: RETURN A[1] 3 ENTFERNE_MAX (A) 1: A[1] ← A[n] 2: n ← n-1 3: VERHALDE (A,1) EINFUEGEN (A,x) 1: n←n+1 , A[n]←x , i←n 2: WHILE i>1 AND A[i]>A[VATER(i)] DO 3: VERTAUSCHE (A[i],A[VATER(i)]) 4: i←Vater(i) Die Laufzeiten betragen für MAXIMUM, ENTFERNE_MAX und EINFUEGEN respektiv O(1), O(log n) und O(log n). Mittels Einfügen kann eine Halde natürlich auch aufgebaut werden. Diese Variante ist jedoch inezient. BAUE_HALDE_LANGSAM(A) 1: N ← 1 2: FOR i=2 TO n DO 3: EINFUEGEN (A,A[i]) Die Laufzeit beträgt n X T (n) = O ! = O(n log n). ldi i=2 | {z } <(n−1)·ldn Diese asymptotische Schranke ist schon scharf, da n X i=2 ldi > n X i= n 2 ldi > n n n n ld = ldn − = Ω(n log n). 2 2 2 2 Die Laufzeit ist also mit T (n) = Θ(n log n) deutlich langsamer als BAUE_HALDE, das eine Halde in linearer Zeit bilden kann. 4