Prioritätslisten, Implementierung mit Binary Heaps

Transcription

Prioritätslisten, Implementierung mit Binary Heaps
Einfügen
h: a c g r d p h w t s z q
j: 1 2 3 4 5 6 7 8 9 10 11 12 13
Procedure insert(e : Element )
assert n < w
n++ ; h[n]:= e
siftUp(n )
Procedure siftUp(i : N)
assert the heap property holds
except maybe at position i
if i = 1 ∨ h[bi /2c] ≤ h[i ] then return
swap(h [i ], h [bi /2c])
siftUp(bi /2c)
a
c g
r d p h
a
c b
w t s z q
r d g h
insertb
w t s z q p
231
Function
deleteMin
: Element
h[1] : Element
h[1]:= h[n]; n−−
result=
siftDown(1)
return
result
compare swap
1
3
4
1
6
9 8
7
3
7 4
1
6
9 8
3
7
4
1
6
9 8
3
4
7
6
9 8
232
Function
deleteMin
compare swap
: Element
h[1] : Element
h[1]:= h[n]; n−−
result=
siftDown(1)
1
3
1
6
7
3
1
6
3
7
1
6
3
4
6
4 9 8 7 4 9 8 4 9 8 7 9 8
return result
Procedure siftDown(i : N)
assert heap property except, possibly at j = 2i and j = 2i + 1
if 2i ≤ n then
// i is not a leaf
if 2i + 1 > n ∨ h[2i ] ≤ h[2i + 1] then m:= 2i else m:= 2i + 1
assert 6 ∃sibling(m) ∨ h[sibling(m)] ≥ h[m]
if h[i ] > h[m] then
// heap property violated
swap(
h[i ], h[m])
m)
siftDown(
assert the heap property holds for the subtree rooted at i
233
deleteMin: Beispiel
1 2 3 4 5 6 7 8 9 10 11 12 13
a
c g
deleteMin
r d p h
c
d g
w t s z q
r q p h
w t s z
234
Binärer Heap Analyse
I
I
I
I
I
Satz: min dauert O(1).
Lemma: Höhe ist blog nc
Satz: insert dauert O(log n).
Satz: deleteMin dauert O(log n).
Beweis: Zeit O(1) pro Schicht.
235
Binärer Heap Konstruktion
Procedure buildHeapBackwards
for i := bn/2c downto 1 do
i)
siftDown(
236
Beispiel: Binärer Heap Konstruktion
9
6
4 31
8
7
compare swap
9
9
6
1
3
1
4 38 7 4 68 7
1
3
4 68
7
9
237
Binärer Heap Konstruktion
I
I
Satz: buildHeap läuft in Zeit O(n)
Beweis: Sei k = blog nc.
In Tiefe
`
I
2
` ∈ 0.. blog nc:
Aufrufe von siftDown
I Kosten je
O(k − `).
Insgesamt:
!
O
∑
0≤`<k
2
`
(k − `) =O 2k
∑
0≤`<k
k −`
2k −`
!
= O 2k
j
!
∑ j
j ≥1 2
| {z }
O(1)!
=O 2k = O(n)
238
Ein nützlicher Rechentrick
∑ j · 2−j = ∑ 2−j + ∑ 2−j + ∑ 2−j + . . .
1/2 +
j ≥1
j ≥1
j ≥2
j ≥3
= (1 + 1/2 + 1/4 + 1/8 + . . .) · ∑ 2−j
j ≥1
= 2·1 = 2
1/4 +
1/4 +
1/8 +
1/8 +
1/8 +
1/16 + ... = 1
1/16 + ... = 1/2
1/16 + ... = 1/4
1/16 + ... = 1/8
...
= ...
____________________________________________
1*1/2 + 2*1/4 + 3*1/8 + 4*1/16 + ... = 2
239
Heapsort
Procedure
heapSortDecreasing(
buildHeap(
a)
for i := n downto
2
h[i ]:= deleteMin
Laufzeit:
a[1..n])
do
O(n log n)
Andere Sichtweise: eziente Implementierung von
Sortieren durch Auswahl
Frage: Wie sortiert man aufsteigend?
240
Heapsort: Beispiel
compare swap
9
3
1
3
7
3
7
4
8
7
4 68 9 4 68 1 9 68 1
4
8
6
6
7
6
7
8
7
9 8 31 9
431 9
431
7
9
8
8
9
8
9
6431
76431
76431
4
7
31
9 6
9
8
7
6431
9
876431
241
Heapsort
↔
Quicksort
↔
Mergesort
Heapsort
Vergleiche
E[Vergleiche]
zusätzl. Platz
Cachezugrie
B =Blockgröÿe)
(
O(n log n)
O(n log n)
O(1)
O(n log n)
Quicksort
O n2
O(n log n)
O(log n) O Bn log n
Mergesort
O(n log n)
O(n log n)
O(n) O Bn log n
Kompromiss: z. B.
introspektives Quicksort der C++ Standardbibliothek:
Quicksort starten. Zu wenig Fortschritt? Umschalten auf Heapsort.
242
Adressierbare Prioritätslisten
Procedure build({e1 , . . . , en }) M := {e1 , . . . , en }
Function size return |M |
Procedure insert(e ) M := M ∪ {e }
Function min return min M
Function deleteMin e := min M ; M := M \ {e }; return e
Function remove(h : Handle) e := h; M := M \ {e }; return e
Procedure decreaseKey(h : Handle, k : Key)
assert key(h) ≥ k ; key(h):= k
Procedure merge(M 0 ) M := M ∪ M 0
243
Adressierbare Prioritätslisten: Anwendungen
Greedy-Algorithmus:
while
solution not complete
do
add the best available piece to the solution
update piece priorities
// e.g., using addressable priority queue
Beispiele:
I Dijkstras Algorithmus für kürzeste Wege
I Jarník-Prim Algorithmus für minimale Spannbäume
I Scheduling: Jobs
→
am wenigsten belastete Maschine
I Hierarchiekonstruktion für Routenplanung
I Suche nach erfüllenden Belegungen aussagenlog. Formeln?
244
Adressierbare Binäre Heaps
1
3
Problem: Elemente bewegen sich.
4
Dadurch werden Elementverweise ungültig.
7
68
9
Ausweg: Unbewegliche Vermittler-Objekte.
Invariante: proxy(e ) verweist auf Position von e .
(Ein)
Vermittler bei jeder Vertauschung aktualisieren.
Rückverweis Element
→
1
Vermittler
3
4
7
6
Laufzeit:
O(log n)
für alle Operationen ausser merge und buildHeap, die
8
9
O(n)
brauchen.
245
Adressierbare Prioritätslisten Laufzeiten
Operation
build
size
min
insert
deleteMin
remove
decreaseKey
merge
Binary Heap
Fibonacci Heap (Buch)
O(n)
O(1)
O(1)
O(log n)
O(log n)
O(log n)
O(log n)
O(n)
O(n)
O(1)
O(1)
O(1)
O(log n)
O(log n)
O(1) am.
O(1)
246
Prioritätslisten: Mehr
I Untere Schranke
Ω (log n)
für deleteMin, vergleichsbasiert. Übung
I ganzzahlige Schlüssel (stay tuned)
I extern: Geht gut (nichtaddressierbar)
I parallel: Semantik?
247
Prioritätslisten: Zusammenfassung
I Häug benötigte Datenstruktur
I Addressierbarkeit ist nicht selbstverständlich
I Binäre Heaps sind einfache, relativ eziente Implementierung
248
Was haben wir jenseits von Prioritätslisten gelernt?
I implizites Layout von Binärbäumen
I
∑j j 2j
I Heapsort (inplace!)
249