Laufzeit von Quicksort im Mittel. Wir wollen die erwartete Effizienz

Werbung
Laufzeit von Quicksort im Mittel. Wir wollen die erwartete Effizienz von
Quicksort ermitteln. Wir nehmen an, die Wahrscheinlichkeit, dass das gewählte
Pivot-Element aj das k-t kleinste Element der Folge ist, ist gleich für alle k =
1, . . . , n und damit ist gleich n1 . Die obige Beschreibung der Laufzeit für ein
bestimmtes k können wir also erweitern und erhalten die folgende Gleichung für
den mittleren Fall:
n
1X
(T (k − 1) + T (n − k))
T (n) = (n − 1) +
n
k=1
Bis auf die Reihenfolge, in der sie auftreten, sind die von den Ausdrücken T (k−1)
und T (n − k) erzeugten Summanden gleich, deshalb lässt sich die Summe kürzer
schreiben:
= (n − 1) +
n−1
2X
T (k)
n
k=0
Wir multiplizieren auf beiden Seiten mit n und ersetzen n durch n − 1:
nT (n) = n(n − 1) + 2
n−1
X
T (k)
k=0
(n − 1)T (n − 1) = (n − 1)(n − 2) + 2
n−2
X
T (k)
k=0
Um T (n) und T (n − 1) miteinander in Verbindung zu bringen, ziehen wir die
oberen beiden Zeilen voneinander ab und erhalten:
nT (n) − (n − 1)T (n − 1) = 2(n − 1) + 2T (n − 1)
nT (n) − (n + 1)T (n − 1) = 2(n − 1)
n+1
n−1
T (n) =
T (n − 1) + 2(
)
n
n
Da lim 2 n−1
n = 2 · lim
n→∞
n→∞
n−1
n
= 2, wird dieser Teil gestrichen und wir erhalten
eine (hinreichend genaue) Ungleichung:
T (n) ≤
n+1
T (n − 1)
n
Wir entwickeln die Formel ein weiteres mal, multiplizieren dann aus und erweitern beim Ergebnis die letzte 2 um den Faktor n+1
n+1 :
n + 1 n
T (n − 2) + 2 + 2
n
n−1
n+1
n+1
n+1
=
T (n − 2) + 2
+2
n−1
n
n+1
T (n) ≤
7
Wir setzen noch einmal ein:
=
n + 1n − 1
n+1
n+1
T (n − 3) + 2 + 2
+2
n−1 n−2
n
n+1
n+1
n+1
n+1
n+1
=
T (n − 3) + 2
+2
+2
n−2
n−1
n
n+1
Wir können jetzt erahnen, wie die Folge aussieht. Um sie korrekt herzuleiten,
müsste an dieser Stelle ein Induktionsbeweis geführt werden, aber uns genügt
das intuitive“ Ergebnis:
”
T (k) =
n+1
n+1
n+1
n+1
n+1
T (n − k) + 2
+2
+2
+ ... + 2
n−k+1
n−k+2
n−k+3
n−k+4
2n − k + 1
Setze k = n:
T (n) =
1 1
n+1
1 T (0) + 2(n + 1)
+ + ... +
1
2 3
n+1
Zur Abschätzung dieser Formel benötigen wir die harmonischen Zahlen. Sie sind
n
P
1
wie folgt definiert: Hn =
k.
k=1
Wir betrachten die Graphen der Funktionen f (x) =
1
x
und g(x) =
1
x+1
4
f(x)
g(x)
Hn
3.5
3
2.5
2
1.5
1
0.5
0
0
0.5
1
1.5
2
2.5
3
3.5
Die harmonischen Zahl Hn kann geometrisch interpretiert werden als die Größe
der Fläche, die sich aus den Rechtecken mit den Flächen der Größe k1 · 1 für
8
4
alle k = {1, . . . , n} zusammensetzt. Der Graph von f begrenzt diese Fläche
offenbar von oben, der Graph von g von unten. Also können wir Hn mit Hilfe
von Integralen abschätzen. Da wir f nicht von 0 integrieren können, beginnen
wir bei 1 und addieren noch 1 für das erste Rechteck hinzu.
Z
n
Hn ≤
Z1 n
Hn ≥
0
1
dx + 1 = 1 + ln n − ln 1 = 1 + ln n
x
1
dx = ln(n + 1)
x+1
Die Abschätzung ist recht genau: Der Unterschied zwischen den Schranken ist
höchstens 1 (genauer: die Euler-(Mascheroni-)Konstante, also ' 0, 5772156649).
Es gilt somit:
Hn = Θ(ln n)
bzw. sogar
Hn = ln n + Θ(1)
Nun ist es uns möglich, die erwartete Laufzeit von Quicksort abzuschätzen:
T (n) ≤ 2(n + 1)(Hn+1 − 1) ≤ 2(n + 1) ln n + 1 = 2n · ln n + Θ(ln n)
Umgerechnet in den Zweierlogarithmus:
T (n) ≤
2n log n
+ Θ(log n) ' 1,38n · log n + Θ(log n)
log e
Zusammengefasst haben wir folgende Laufzeiten für die Algorithmen Mergesort
(A4) und Quicksort (A4) ermittelt:
Mergesort: n · log n+ lineare Terme
Quicksort: 1,38n · log n+ logarithmische Terme
Ein erster Vergleich zeigt, dass Quicksort etwa um den Faktor 1,38 langsamer
ist. Wir werden gleich darauf zurück kommen, warum dies in der Praxis etwas
anders aussieht.
Vergleich der 4 Algorithmen in der Praxis. Einige Zahlen sollen zeigen,
dass der Unterschied der Algorithmen bei realer Rechenzeit trotz immer schneller werdender Prozessoren noch erheblich ist und ein Nachdenken über effiziente
Algorithmen sich durchaus lohnt.
9
Die Anzahl der durchgeführten Vergleiche bei einer Eingabe der Länge n:
n
10
20
50
n · log n
33
86
282
1 2
2n
−
45
190
1225
n
2
n!
3,6 · 106
2,4 · 1018
3,0 · 1064
Größe der Probleme, die eine Maschine mit 109 Vergleichen pro Sekunde mittels
der Algorithmen lösen kann:
1 Sekunde
1 Stunde
n · log n
4 · 107
1 · 1011
1 2
2n
− n2
4,0 · 104
2,6 · 106
n!
13
16
Dasselbe für eine 10-mal schnellere Maschine:
1 Sekunde
1 Stunde
n · log n
3,5 · 108
9,1 · 1011
− n2
1,0 · 105
8,4 · 106
1 2
2n
n!
14
17
Man sieht: Bei schneller werdendem Rechner wächst die Größe der berechenbaren Probleme bei schlechten Algorithmen entsprechend langsam – bei dem
Algorithmus, der alle Permutationen eines Arrays durchgeht, um den sortierten
zu finden, kann hier mit einem 10-mal schnelleren Rechner gerade mal ein um
ein Feld längeres Array berechnet werden.
Vergleich von Quicksort und Mergesort. Wenn man, wie hier, nur die
Anzahl der Vergleiche als Maß nimmt, ist Mergesort zwar schneller, in der Realität wird aber Quicksort effizienter sein, weil es weniger Daten im Speicher lesen
und schreiben muss. Bei Mergesort müssen die Daten in zwei getrennten Arrays
abgelegt werden, Quicksort kann immer im selben Array operieren.
Bei einer großen Anzahl von Vergleichen (bei einem handelsüblichen PC bei
ca. 4000000) sieht man deshalb auch einen deutlichen Anstieg des Aufwands bei
Mergesort. Dies liegt daran, dass irgendwann der Hauptspeicher voll ist und der
Hintergrundspeicher (Swap) benutzt werden muss. Es gibt einen eigenen Zweig
der Forschung, der Algorithmen entwickelt, die den Zugriff auf den Hintergrundspeicher vermeiden oder minimieren, weil es durchaus Probleme gibt, die derart
viel Platz brauchen, dass dies stark ins Gewicht fällt. Beispiele finden sich etwa
in der Meteorologie, wo Programme mit Millionen von Einzeldaten operieren.
1.2
Berechnungsmodelle
Berechnungsmodelle sind mathematische Modelle für Rechner, die verwendet
werden, um präzise Aussagen über Berechnungen treffen zu können. Begriffe
wie etwa Algorithmus“, Laufzeit“ oder Speicher“ werden mit ihnen formal
”
”
”
definiert. Das bekannteste Beispiel ist wohl die 1936 von Alan Turing entwickelte
10
Turingmaschine, die in dieser Vorlesung aber nicht eigens wiederholt wird.
Definition 1.2.1 (Registermaschine (Random Access Machine, RAM)). Eine Registermaschine besteht aus einem unendlichen, aus den Zellen R0 , R1 , ...
bestehenden Speicher. Diese können jeweils eine beliebig große ganze Zahl enthalten. Die Unbegrenztheit von Speicher und Inhalt einer Zelle stellen somit
jeweils eine Abstraktion von realen Computern dar.
Ein Programm ist eine endliche Folge von Befehlen. Ein Beispiel-Befehlssatz
könnte etwa wie folgt aussehen. Ein in klammern gesetztes Register (Ri ) steht
hier für den Wert der Speicherzelle Rj , wobei j der Wert von Ri ist.
A := B op C
A := B
goto L
GGZ B, L
GLZ B, L
GZ B, L
HALT
wobei A : Ri oder (Ri ), i ∈ N0
B, C : Ri oder (Ri ), i ∈ N0 oder Konstante k ∈ N0
op ∈ {+, −, ∗, /}
wobei L eine Zeile des Programms ist
gehe nach L, wenn B > 0
gehe nach L, wenn B < 0
gehe nach L, wenn B = 0
Beende Abarbeitung des Programms
Jedem Befehl kann man so eine Semantik zuordnen. Auch dies kann man formalisieren – den Zustand einer RAM kann man beschreiben, indem man mit
einer Funktion c : N → Z angibt, welcher Wert in jeder Speicherzelle steht.
Wenn man dazu eine eine Menge von Funktionen definiert, die für jeden Zustand und jeden Befehl den Folgezustand angeben, hätte man eine vollständige
operationelle Semantik.
Definition 1.2.2 (Berechnung einer Funktion auf einer RAM). Eine Registermaschine R berechnet eine Funktion f : Z∗ → Z∗ bedeutet: Falls in den ersten
m Speicherzellen eine Folge a0 , ..., am steht, rechnet“ R (läuft, bis es zu einem
”
HALT-Befehl kommt) und hat dann f (a0 , . . . , am ) = (b0 , . . . , bn ) in die ersten
Speicherzellen geschrieben.
1.2.1
Laufzeit und Speicherbedarf einer RAM
Wir wollen nun die Laufzeit und den Speicherbedarf eine RAM formal definieren.
Dafür gibt es verschiedene Kriterien, von denen hier zwei vorgestellt werden.
Das Einheitskostenmaß (EKM): Man nimmt an, dass erstens die Ausführung von jedem Befehl indifferent eine Zeiteinheit kostet, und dass zweitens ein
Register unabhängig von seinem Inhalt eine Speichereinheit belegt.
Dieses Maß ist Proportional zu den Kosten auf einem normalen Rechner, aber
nur für beschränkt große Operanden: In der Realität wird eine Addition von
zwei 1000-stelligen Zahlen mehr kosten als die von 2 oder 3-stelligen, weil eine
1000-stellige Zahl auf einem tatsächlichen Computer nicht von einem einzigen
Register/ einer einzelnen Speicherstelle dargestellt wird.
11
Das logarithmische Kostenmaß: Beim logarithmischen Kostenmaß geht
die Größe der Zahlen, mit denen man operiert, in die Berechnung der Kosten
mit ein. Außerdem unterscheidet man, auf welches Register man zugreift.
Wenn n eineP
Zahl ist, sei L(n) die Länge der Binärdarstellung von n. Ein Befehl
kostet dann k L(k), wobei k als Wert alle involvierten Adressen und die Werte
aller Operanden annimmt.
12
Herunterladen