Handout - TU Ilmenau

Werbung
Algorithmen und Datenstrukturen SS09
Foliensatz 14
Michael Brinkmeier
Technische Universität Ilmenau
Institut für Theoretische Informatik
Sommersemester 2009
Algorithmen und Datenstrukturen SS09
M. Brinkmeier
TU Ilmenau
Seite 1 / 35
Heapsort
Algorithmen und Datenstrukturen SS09
M. Brinkmeier
TU Ilmenau
Seite 2 / 35
Heaps
Heapsort verwendet sogenannte Heaps (Haufen), d.h. Binärbäume deren
Knotenmarkierungen bestimmte Bedingungen erfüllen:
Definition (Max-Heap)
Ein U-Binärbaum T für eine total geordnete Menge (U, <) ist ein Max-Heap
(oder heißt max-heapgerodnet), wenn für jeden Knoten v gilt:
Ist w ein Kind von v , dann gilt key(v ) ≥ key(w )
(Heapbedingung)
17
12
14
4
11
2
3
2
13
10
Algorithmen und Datenstrukturen SS09
M. Brinkmeier
TU Ilmenau
Seite 3 / 35
Heaps
Anstatt den Knoten größer als seine Kinder zu wählen, kann man ihn auch
kleiner wählen.
Definition (Min-Heap)
Ein U-Binärbaum T für eine total geordnete Menge (U, <) ist ein Min-Heap
(oder heißt min-heapgerodnet), wenn für jeden Knoten v gilt:
Ist w ein Kind von v , dann gilt key(v ) ≤ key(w )
(Heapbedingung)
2
2
10
3
4
14
12
13
Algorithmen und Datenstrukturen SS09
M. Brinkmeier
TU Ilmenau
Seite 4 / 35
11
17
Heaps und das Maximum
Beobachtung
Ist T = (T1 , x, T2 ) ein Max/Min-Heap, dann sind auch T1 und T2
Max/Min-Heaps.
Lemma
Ist T ein Max-Heap, dann enthält die Wurzel ein maximales Element.
Beweis (Induktion über die Form von T )
Für T = (x) ist die Behauptung offensichtlich korrekt.
Für T = (T1 , x, T2 ) sind die beiden Teilbäume T1 und T2 ebenfalls
Max-Heaps.
Damit sind die Schlüssel in ihren Wurzeln maximal in diesen Teilbäumen. Da
x ≥ max{key(T1 ), key(T2 )} gilt, ergibt sich somit
x ≥ key(v ) für jeden Knoten v in T .
Algorithmen und Datenstrukturen SS09
M. Brinkmeier
TU Ilmenau
Seite 5 / 35
Heaps und das Minimum
Analog erhält man:
Lemma
Ist T ein Min-Heap, dann enthält die Wurzel ein minimales Element.
Algorithmen und Datenstrukturen SS09
M. Brinkmeier
TU Ilmenau
Seite 6 / 35
Die Grundidee von Heapsort
Idee
Nutze Heaps, um schnell das Maximum/Minimum zu ermitteln.
Heapsort läuft in zwei Phasen ab:
1
2
Bilde einen Max-Heap.
Für i = n − 1, . . . , 1 tue folgendes:
1
2
Entferne das Maximum aus dem Heap und kopiere es an die letzte Stelle
des Ergerbnisfeldes.
Bilde aus den restlichen Elementen einen neuen Heap.
Algorithmen und Datenstrukturen SS09
M. Brinkmeier
TU Ilmenau
Seite 7 / 35
Die Grundidee von Heapsort
Es stellen sich mehrere Fragen:
Muss man tatsächlich einen Binärbaum bauen?
Wie baut man den Heap, bzw. wie stellt man die Heapbedingung her?
Wie erhält man wieder einen Heap, nachdem das Maximum entfernt
wurde?
Algorithmen und Datenstrukturen SS09
M. Brinkmeier
TU Ilmenau
Seite 8 / 35
Felder und binäre Bäume
Wir interpretieren ein Feld A[1 . . . n] als binären Baum, indem wir beginnend
mit der Wurzel, die Ebenen des Baumes sequentiell mit den Einträgen des
Feldes füllen (Levelorder).
Für n = 10 ergibt sich somit der folgende Baum:
Tiefe 0
A[1]
Tiefe 1
A[2]
Tiefe 2
Tiefe 3
A[4]
A[8]
A[3]
A[5]
A[9]
A[6]
A[7]
A[10]
D.h. in Tiefe i befinden sich die Schlüssel S[2i . . . 2i +1 − 1].
Algorithmen und Datenstrukturen SS09
M. Brinkmeier
TU Ilmenau
Seite 9 / 35
Felder und binäre Bäume
Tiefe 0
A[1]
Tiefe 1
A[2]
Tiefe 2
Tiefe 3
A[4]
A[8]
A[3]
A[5]
A[9]
A[6]
A[7]
A[10]
Die Nachfolger eines Eintrags und sein Vorgänger lassen sich auf einfache
Art über die Indices im Feld ermitteln.
Der linke Nachfolger von A[i] ist A[2i]
Der rechte Nachfolger von A[i] ist A[2i + 1]
Der Vorgänger von A[i] ist A[⌊i/2⌋]
Algorithmen und Datenstrukturen SS09
M. Brinkmeier
TU Ilmenau
Seite 10 / 35
Die Heapbedingung
Die Heapbedingung lässt sich für Arrays auf die folgende Art formulieren:
Definition (Array als Heap)
Ein Feld A[1 . . . n] von Schlüsseln ist ein (Max-)Heap (Haufen), wenn für alle
k mit 2 ≤ k ≤ n gilt
A [⌊k/2⌋] ≥ A[k],
d.h. der Wert des Vaters ist mindestens so groß wie jedes seiner Kinder.
Für 1 ≤ l ≤ n ist A ist ein (Max-)Heap ab l, wenn für alle k mit
l ≤ ⌊k/2⌋ < k ≤ n gilt
A [⌊k/2⌋] ≥ A[k].
Min-Heaps sind analog definiert, lediglich die Relation zwischen Vater und
Kindern ist umgedreht.
Algorithmen und Datenstrukturen SS09
M. Brinkmeier
TU Ilmenau
Seite 11 / 35
Herstellen der Heapbedingung
Wir betrachten einen Knoten mit Schlüssel x. Seine beiden Unterbäume T1
und T2 seien heapgeordnet. Die Wurzel von T1 sei y , und z die von T2 .
x
y
z
T1
T2
Fall 1: Wenn x ≥ y , z, dann ist der Baum bereits ein Max-Heap.
Algorithmen und Datenstrukturen SS09
M. Brinkmeier
TU Ilmenau
Seite 12 / 35
Herstellen der Heapbedingung
x
y
z
T1
T2
Fall 2: Wenn y > x, z, dann muss y in die Wurzel, denn es ist der
maximale Schlüssel im Baum.
Anschließend muss die Heapbedingung in T1 wieder hergestellt werden. Dies
erfolgt im Prinzip rekursiv.
Fall 3: z > x, y wird analog behandelt.
Algorithmen und Datenstrukturen SS09
M. Brinkmeier
TU Ilmenau
Seite 13 / 35
BubbleDown
BubbleDown rekursiv(A, i , r )
Eingabe: Array A[1 . . . n], Länge r und Index i
Voraussetzung: Die Teilbäume mit den Wurzeln 2i und 2i + 1 sind heapgeordnet.
wenn (2i > r ) dann return;
//
j = 2i;
wenn 2i + 1 ≤ r und A[2i + 1] > A[2i] dann
j = 2i + 1 ;
Ende
wenn A[j] > x dann
Vertausche A[i] und A[j];
BubbleDown rekursiv(A, j, r );
//
//
Algorithmen und Datenstrukturen SS09
Seite 14 / 35
A[j] ist größeres Kind
Tausche Wurzel mit größerem Kind
//
Ende
M. Brinkmeier
TU Ilmenau
A[i ] hat keine Nachfolger
Mache bei A[j] weiter
Ein Beispiel für RekHeapify
477
77
462
774
62
72
21
14
454
54
62
4
12
35
37
54
4
14
12
Algorithmen und Datenstrukturen SS09
M. Brinkmeier
TU Ilmenau
Seite 15 / 35
BubbleDown – Iterative Formulierung
BubbleDown(A, i , r )
done = false, A = A[i];
solange done == false und 2i ≤ r tue
j := 2i;
// Wähle das
wenn 2i + 1 ≤ r und A[2i] < A[2i + 1] dann j := 2i + 1;
//
Falls Kind größer als Vater, schiebe Kind hoch und mache an dessen alter
Position weiter
wenn A < A[j] dann A[i] = A[j], i := j;
// Falls Vater größer,
sonst done = true;
// Bringe
A[i] = A;
Ende
höre auf
die ursprüngliche Wurzel an die neue Stelle
Algorithmen und Datenstrukturen SS09
M. Brinkmeier
TU Ilmenau
größere Kind von A[j]
Seite 16 / 35
BubbleDown
Die Routine BubbleDown(A, i, r ) lässt somit das Element an Position i von
oben nach unten an die korrekte Position sickern.
Dabei ist die Voraussetzung, dass A ab 2i und 2i + 1 bereits ein Heap ist,
essentiell.
Korrektheit von BubbleDown ist eine Übungsaufgabe.
Algorithmen und Datenstrukturen SS09
M. Brinkmeier
TU Ilmenau
Seite 17 / 35
Ablauf von Heapsort
1
Zu Beginn baut Heapsort einen Heap aus dem Feld.
2
Da wir keinerlei weitere Einschränkung machen, muss der Heap von
unten nach oben gebaut werden. D.h. wir machen erst die Teilbäume zu
Heaps und lassen anschließend die Wurzel mittels BubbleDown an die
korrekte Position sickern.
3
Ist der Heap fertig, steht ein maximaler Schlüssel in der Wurzel. Er wird
mit dem Schlüssel an der letzten Stelle des Feldes getauscht.
Dadurch verkürzt sich das Feld der unsortierten Schlüssel um eins.
Außerdem ist das Feld ab 2 bis n − 1 weiterhin ein Heap (durch den
Tausch verändert sich nur der Wert der Wurzel). Dadurch kann es durch
einen Aufruf von BubbleDown wieder zu einem Heap umgebaut werden.
4
Dies wird wiederholt, bis keine Schlüssel mehr zu sortieren sind.
Algorithmen und Datenstrukturen SS09
M. Brinkmeier
TU Ilmenau
Seite 18 / 35
Heapsort
Im Pseudocode hat Heapsort die folgende Form:
Heapsort
Beginn
// Der Heap wird von unten nach oben gebaut,
für j := ⌊ n2 ⌋ . . . 1 tue BubbleDown(A, j, n);
beginnend in der vorletzten Ebene.
// Solange noch ein Element im Heap ist, entferne das Maximum (die Wurzel)
für r := n − 1 . . . 1 tue
// Runterzählen von r = Verkürzung des Heaps
Vertausche A[1] und A[r + 1];
// Bringe Wurzel an das Ende
BubbleDown(A, 1, r );
// Wurzel muss an die korrekte Stelle sickern.
Ende
Ende
Algorithmen und Datenstrukturen SS09
M. Brinkmeier
TU Ilmenau
Seite 19 / 35
Korrektheit
Der Beweis der Korrektheit von Heapsort ist eine Übungsaufgabe.
Algorithmen und Datenstrukturen SS09
M. Brinkmeier
TU Ilmenau
Seite 20 / 35
Ein Beispiel
2 3 4 5 6 7 8
Algorithmen und Datenstrukturen SS09
M. Brinkmeier
TU Ilmenau
Seite 30 / 35
Die Laufzeit von BubbleDown
Beobachtung
Für die Laufzeit von BubbleDown ist die Anzahl der Schlüsselvergleiche
ausschlaggebend.
In jeder Runde werden im Maximum zwei Vergleiche gemacht:
1
Vergleich der beiden Kinder, um das größere zu finden.
2
Vergleich des größeren Kindes mit dem aktuellen Knoten.
Für die Runde j sei ij der Index des aktuellen Knotens. Ferner ser r der
Endindex.
Dann gilt offenbar ij+1 ≥ 2ij und für jede durchgeführte Runde gilt ij ≤ r .
Damit gilt 2j−1 i1 ≤ ij ≤ n und somit gilt für jede durchgeführte Runde j
(j − 1) + log i1 ≤ log r
Algorithmen und Datenstrukturen SS09
M. Brinkmeier
TU Ilmenau
Seite 31 / 35
Die Laufzeit von BubbleDown
Lemma
Beim Aufruf BubbleDown(A, i, r ) werden höchstens 2 · log r − log i
Schlüsselvergleiche durchgeführt.
BubbleDown(A, i, r ) benötigt im schlechtesten Fall Zeit O(log n − log i).
Algorithmen und Datenstrukturen SS09
M. Brinkmeier
TU Ilmenau
Seite 32 / 35
Laufzeit von Heapsort
Betrachtet man die Aufrufe von BubbleDown, so ergeben sich die folgenden
Parameterkombinationen:
i
r
Laufzeit
n
..
.
n
..
.
O(1)
..
.
2
n
O(log n − 1)
1
n
O(log n)
1
n−1
O(log(n − 1))
1
..
.
n−2
..
.
O(log(n − 2))
..
.
1
1
O(1)
2
Aufbauphase:
n
P
O(log i) ≤ O(n log n)
i =1
Wegnahmephase:
n−1
P
O(log i) ≤ O(n log n)
i =1
Gesamt: O(n log n)
Algorithmen und Datenstrukturen SS09
M. Brinkmeier
TU Ilmenau
Seite 33 / 35
Laufzeit von Heapsort
Satz
Heapsort benötigt zum Sortieren eines Feldes mit n Einträgen im
schlechtesten Fall O(n log n) Schlüsselvergleiche und Zeit.
Bemerkungen
Um absteigend zu sortieren, muss lediglich ein Min-Heap benutzt
werden, d.h. die Relation in den Schlüsselvergleichen muss umgedreht
werden.
Die mittlere Anzahl von Vergleichen, unter der Annahme, dass jede
Anordnung der Eingabeobjekte mit der WS 1/n! auftritt, ist ungefähr
2n log n.
Durch eine Änderung von BubbleDown lässt sich die mittlere Zahl der
Vergleiche auf n log n + O(n) senken. Bei Bottom-Up-Heapsort, wird
zuerst der Weg der größeren Kinder bis zu einem Blatt verfolgt.
Anschließend wird von unten die korrekte Stelle gesucht.
Algorithmen und Datenstrukturen SS09
M. Brinkmeier
TU Ilmenau
Seite 34 / 35
Herunterladen