Analyse von Quicksort

Werbung
Quicksort
June 6, 2010
Quicksort (C.A.R. Hoare, Computer Journal, 1962)
Quicksort (C.A.R. Hoare, Computer Journal, 1962)
I
Klassisches, sehr beliebtes, weil im Mittel sehr effizientes
Sortierverfahren
Quicksort (C.A.R. Hoare, Computer Journal, 1962)
I
Klassisches, sehr beliebtes, weil im Mittel sehr effizientes
Sortierverfahren
I
In vielen Systemen (Unix) das Standardverfahren
Quicksort (C.A.R. Hoare, Computer Journal, 1962)
I
Klassisches, sehr beliebtes, weil im Mittel sehr effizientes
Sortierverfahren
I
In vielen Systemen (Unix) das Standardverfahren
I
Basiert auf “dynamischem” (datengetriebenem)
divide-and-conquer
Quicksort (C.A.R. Hoare, Computer Journal, 1962)
I
Klassisches, sehr beliebtes, weil im Mittel sehr effizientes
Sortierverfahren
I
In vielen Systemen (Unix) das Standardverfahren
I
Basiert auf “dynamischem” (datengetriebenem)
divide-and-conquer
I
Wenig zusätzlicher Speicherplatz (O(log2 n) bei Listelänge n)
Quicksort (C.A.R. Hoare, Computer Journal, 1962)
I
Klassisches, sehr beliebtes, weil im Mittel sehr effizientes
Sortierverfahren
I
In vielen Systemen (Unix) das Standardverfahren
I
Basiert auf “dynamischem” (datengetriebenem)
divide-and-conquer
I
Wenig zusätzlicher Speicherplatz (O(log2 n) bei Listelänge n)
I
Vorsicht: worst-case Verhalten ist ineffizient!
Quicksort (C.A.R. Hoare, Computer Journal, 1962)
I
Klassisches, sehr beliebtes, weil im Mittel sehr effizientes
Sortierverfahren
I
In vielen Systemen (Unix) das Standardverfahren
I
Basiert auf “dynamischem” (datengetriebenem)
divide-and-conquer
I
Wenig zusätzlicher Speicherplatz (O(log2 n) bei Listelänge n)
I
Vorsicht: worst-case Verhalten ist ineffizient!
I
Paradoxon: worst-case tritt z.B. bei schon sortierten Listen ein
Quicksort (C.A.R. Hoare, Computer Journal, 1962)
I
Klassisches, sehr beliebtes, weil im Mittel sehr effizientes
Sortierverfahren
I
In vielen Systemen (Unix) das Standardverfahren
I
Basiert auf “dynamischem” (datengetriebenem)
divide-and-conquer
I
Wenig zusätzlicher Speicherplatz (O(log2 n) bei Listelänge n)
I
Vorsicht: worst-case Verhalten ist ineffizient!
I
Paradoxon: worst-case tritt z.B. bei schon sortierten Listen ein
I
Viele Varianten und Verbesserungen, um worst-case-Verhalten
sehr unwahrscheinlich zu machen
R. Sedgewick in Algorithms:
It is tempting to try to develop ways to improve Quicksort: a faster
sorting algorithm is computer science’s “better mousetrap”. Almost
from the moment Hoare first published the algorithm, “improved”
version have been appearing in the literature.
R. Sedgewick in Algorithms:
It is tempting to try to develop ways to improve Quicksort: a faster
sorting algorithm is computer science’s “better mousetrap”. Almost
from the moment Hoare first published the algorithm, “improved”
version have been appearing in the literature.
Many ideas have been tried and analyzed, but it is easy to be
deceived, because the algorithm is so well balanced that the effects
of improvements in one part of the program can be more than offset
by the effects of bad performance in another part of the program.
R. Sedgewick in Algorithms:
It is tempting to try to develop ways to improve Quicksort: a faster
sorting algorithm is computer science’s “better mousetrap”. Almost
from the moment Hoare first published the algorithm, “improved”
version have been appearing in the literature.
Many ideas have been tried and analyzed, but it is easy to be
deceived, because the algorithm is so well balanced that the effects
of improvements in one part of the program can be more than offset
by the effects of bad performance in another part of the program.
A carefully tuned version of Quicksort is likely to run significantly
faster on most computers than any other sorting method.
R. Sedgewick in Algorithms:
It is tempting to try to develop ways to improve Quicksort: a faster
sorting algorithm is computer science’s “better mousetrap”. Almost
from the moment Hoare first published the algorithm, “improved”
version have been appearing in the literature.
Many ideas have been tried and analyzed, but it is easy to be
deceived, because the algorithm is so well balanced that the effects
of improvements in one part of the program can be more than offset
by the effects of bad performance in another part of the program.
A carefully tuned version of Quicksort is likely to run significantly
faster on most computers than any other sorting method.
However, it must be cautioned that tuning any algorithm can make
it more fragile, leading to undesirable and unexpected effects for
some inputs
I
Zur Implementierung und detailierten Analyse:
R. Sedgewick, Ouicksort (Diss.),
R. Sedgewick, Implementing Quicksort Programs,
Communications of the ACM, 1978,
J.L. Bentley, M.D. McIlroy, Software Practice and
Experience, 1993 (→ Unix)
Divide-and-conquer für das Sortieren
I
A totalgeordneten Menge
Divide-and-conquer für das Sortieren
I
A totalgeordneten Menge
I
a = ha1 , a2 , . . . , an i Liste von Elementen aus A
Divide-and-conquer für das Sortieren
I
A totalgeordneten Menge
I
a = ha1 , a2 , . . . , an i Liste von Elementen aus A
I
Das Element ak in der Position k ist ein Splitter für a, wenn
gilt
ai ≤ ak ≤ aj für alle i < k und alle j > k.
Divide-and-conquer für das Sortieren
I
A totalgeordneten Menge
I
a = ha1 , a2 , . . . , an i Liste von Elementen aus A
I
Das Element ak in der Position k ist ein Splitter für a, wenn
gilt
ai ≤ ak ≤ aj für alle i < k und alle j > k.
I
Ist ak Splitter für a, so kann man das Sortieren der Liste a
durch einen divide-and-conquer-Ansatz erledigen, indem beide
Teillisten
a` = ha1 , a2 , . . . , ak−1 i und ar = hak+1 , ak+2 , . . . , an i
in-place separat sortiert werden – denn das Element ak steht
bezüglich des Sortierens bereits an der richtigen Stelle.
Divide-and-conquer für das Sortieren
I
A totalgeordneten Menge
I
a = ha1 , a2 , . . . , an i Liste von Elementen aus A
I
Das Element ak in der Position k ist ein Splitter für a, wenn
gilt
ai ≤ ak ≤ aj für alle i < k und alle j > k.
I
Ist ak Splitter für a, so kann man das Sortieren der Liste a
durch einen divide-and-conquer-Ansatz erledigen, indem beide
Teillisten
a` = ha1 , a2 , . . . , ak−1 i und ar = hak+1 , ak+2 , . . . , an i
in-place separat sortiert werden – denn das Element ak steht
bezüglich des Sortierens bereits an der richtigen Stelle.
I
Schematisch
sort(a) = hsort(a` ), ak , sort(ar )i
Beispiel
– (3, 1, 2, 4, 7, 5, 6) hat 4 als Splitter
– (5, 1, 2, 4, 7, 3, 6) hat keinen Splitter
– (1, 2, 3, 4, 5, 6, 7) hat alle 7 Positionen als Splitter
Splitter sind selten!
I
Splitter sind selten! Die “meisten” Listen haben überhaupt
keinen Splitter.
Splitter sind selten!
I
Splitter sind selten! Die “meisten” Listen haben überhaupt
keinen Splitter.
I
Sn Menge der n! Permutationen einer n-elementigen
totalgeordneten Menge, z.B. der Zahlen {1, 2, . . . , n}.
Splitter sind selten!
I
Splitter sind selten! Die “meisten” Listen haben überhaupt
keinen Splitter.
I
Sn Menge der n! Permutationen einer n-elementigen
totalgeordneten Menge, z.B. der Zahlen {1, 2, . . . , n}.
Quantitativ
I
I
I
Die Position k ist ein Splitter in (k − 1)! · (n − k)!
Permutationen aus Sn .
Die Gesamtzahl sn der Splitter in Sn
sn :=
n
X
k=1
(k − 1)! (n − k)! = (n − 1)! ·
−1
n−1 X
n−1
k=0
k
Splitter sind selten!
I
Splitter sind selten! Die “meisten” Listen haben überhaupt
keinen Splitter.
I
Sn Menge der n! Permutationen einer n-elementigen
totalgeordneten Menge, z.B. der Zahlen {1, 2, . . . , n}.
Quantitativ
I
I
I
Die Position k ist ein Splitter in (k − 1)! · (n − k)!
Permutationen aus Sn .
Die Gesamtzahl sn der Splitter in Sn
sn :=
n
X
k=1
I
(k − 1)! (n − k)! = (n − 1)! ·
−1
n−1 X
n−1
k=0
k
Für die mittlere Anzahl von Spittern in einer Permutation aus
Sn gilt
sn
2
sn =
∼
n!
n
Hoare’s Idee
I
Mittels einer einfachen Umordnung einer zu sortierenden Liste
das Vorhandensein eines Splitter in einer bekannten Position
zu garantieren
Hoare’s Idee
I
Mittels einer einfachen Umordnung einer zu sortierenden Liste
das Vorhandensein eines Splitter in einer bekannten Position
zu garantieren
I
Das leistet der Algorithmus Split (auch Partition genannt)
Hoare’s Idee
I
Mittels einer einfachen Umordnung einer zu sortierenden Liste
das Vorhandensein eines Splitter in einer bekannten Position
zu garantieren
I
Das leistet der Algorithmus Split (auch Partition genannt)
I
Verfahren rekursiv auf Teillisten vor und hinter dem Splitter
anwenden
Hoare’s Idee
I
Mittels einer einfachen Umordnung einer zu sortierenden Liste
das Vorhandensein eines Splitter in einer bekannten Position
zu garantieren
I
Das leistet der Algorithmus Split (auch Partition genannt)
I
Verfahren rekursiv auf Teillisten vor und hinter dem Splitter
anwenden
Komplexitätsanalyse
I
I
I
Im worst-case ist das ein O(n2 )-Verfahren
Interessant ist der average-case bei zufällig gewählten pivots
Hoare’s Idee
I
Mittels einer einfachen Umordnung einer zu sortierenden Liste
das Vorhandensein eines Splitter in einer bekannten Position
zu garantieren
I
Das leistet der Algorithmus Split (auch Partition genannt)
I
Verfahren rekursiv auf Teillisten vor und hinter dem Splitter
anwenden
Komplexitätsanalyse
I
I
I
I
Im worst-case ist das ein O(n2 )-Verfahren
Interessant ist der average-case bei zufällig gewählten pivots
V quick (n) : die mittlere Anzahl von Vergleichoperationen des
Algorithmus quicksort für Listenlänge n
2
6
1
8
7
5
3
4
2
6
1
8
7
5
3
4
2
6
1
8
7
5
3
4
5
6
1
8
7
2
3
4
2
6
1
8
7
5
3
4
5
6
1
8
7
2
3
4
5
6
1
8
7
2
3
4
2
6
1
8
7
5
3
4
5
6
1
8
7
2
3
4
5
6
1
8
7
2
3
4
5
1
6
8
7
2
3
4
2
6
1
8
7
5
3
4
5
6
1
8
7
2
3
4
5
6
1
8
7
2
3
4
5
1
6
8
7
2
3
4
2
6
1
8
7
5
3
4
5
6
1
8
7
2
3
4
5
6
1
8
7
2
3
4
5
1
6
8
7
2
3
4
5
1
2
8
7
6
3
4
2
6
1
8
7
5
3
4
5
6
1
8
7
2
3
4
5
6
1
8
7
2
3
4
5
1
6
8
7
2
3
4
5
1
2
8
7
6
3
4
5
1
2
8
7
6
3
4
2
6
1
8
7
5
3
4
5
6
1
8
7
2
3
4
5
6
1
8
7
2
3
4
5
1
6
8
7
2
3
4
5
1
2
8
7
6
3
4
5
1
2
8
7
6
3
4
5
1
2
3
7
6
8
4
2
6
1
8
7
5
3
4
5
6
1
8
7
2
3
4
5
6
1
8
7
2
3
4
5
1
6
8
7
2
3
4
5
1
2
8
7
6
3
4
5
1
2
8
7
6
3
4
5
1
2
3
7
6
8
4
5
1
2
3
7
6
8
4
2
6
1
8
7
5
3
4
5
6
1
8
7
2
3
4
5
6
1
8
7
2
3
4
5
1
6
8
7
2
3
4
5
1
2
8
7
6
3
4
5
1
2
8
7
6
3
4
5
1
2
3
7
6
8
4
5
1
2
3
7
6
8
4
5
1
2
3
4
6
8
7
2
6
1
8
7
5
3
4
5
6
1
8
7
2
3
4
5
6
1
8
7
2
3
4
5
1
6
8
7
2
3
4
5
1
2
8
7
6
3
4
5
1
2
8
7
6
3
4
5
1
2
3
7
6
8
4
5
1
2
3
7
6
8
4
5
1
2
3
4
6
8
7
4
1
2
3
5
6
8
7
Algorithm 1 Vertauschen von zwei Listenelementen
procedure Swap(A :: array (integer ), u, v :: integer )
local tmp
if not u = v then
tmp ← A[u]
A[u] ← A[v ]
A[v ] ← tmp
end if
end procedure
Algorithm 2 Splitten einer Liste mit randomisiertem Pivotelement
procedure Split(A :: array (integer ),left,right,pivotpos :: integer )
local i, j, r
r ← rand(left..right)()
Swap(A, left, r )
i ← left
for j = left + 1..right do
if A[j] < A[left] then
i ←i +1
Swap(A, i, j)
end if
end for
Swap(A, left, i)
pivotpos ← i
end procedure
Algorithm 3 Quicksort rekursiv
procedure Qksort(A :: array (integer ), left, right :: integer )
local k
if left < right then
Split(A, left, right, k)
Qksort(A, left, k − 1)
Qksort(A, k + 1, right)
end if
end procedure
Algorithm 4 Quicksort
procedure Quicksort(A :: array (integer ))
Qksort(A, 1, length(A))
end procedure
Kombinatorik/Stochastik des Splittens
I
σ ∈ Sn zufällige Permutation von {1, 2, . . . , n}
Kombinatorik/Stochastik des Splittens
I
σ ∈ Sn zufällige Permutation von {1, 2, . . . , n}
I
zufälliges Element k ∈ {1, 2, . . . , n} als Pivotelement
Kombinatorik/Stochastik des Splittens
I
σ ∈ Sn zufällige Permutation von {1, 2, . . . , n}
I
zufälliges Element k ∈ {1, 2, . . . , n} als Pivotelement
Split erzeugt
I
I
I
zufällige Permutation σ ` ∈ Sk−1 der Menge {1, 2, . . . , k − 1}
(gleichverteilt)
zufällige Permutation σ r der Menge {k + 1, k + 2, . . . , n}
(gleichverteilt)
Kombinatorik/Stochastik des Splittens
I
σ ∈ Sn zufällige Permutation von {1, 2, . . . , n}
I
zufälliges Element k ∈ {1, 2, . . . , n} als Pivotelement
Split erzeugt
I
I
I
I
zufällige Permutation σ ` ∈ Sk−1 der Menge {1, 2, . . . , k − 1}
(gleichverteilt)
zufällige Permutation σ r der Menge {k + 1, k + 2, . . . , n}
(gleichverteilt)
Symbolisch:
σ 7→ hσ ` , k, σ r i
Die Quicksort-Rekursion
I
Aus der Stochastik des Splittens ergibt sich
n
1 X
V quick (n) = (n−1)+ ·
V quick (k − 1) + V quick (n − k)
n
k=1
Die Quicksort-Rekursion
I
Aus der Stochastik des Splittens ergibt sich
n
1 X
V quick (n) = (n−1)+ ·
V quick (k − 1) + V quick (n − k)
n
k=1
I
dies lässt sich umformen zu
n−1
2 X
V quick (n) = (n−1)+ ·
V quick (k) (n ≥ 2),
n
k=0
V quick (1) = 0
Die Quicksort-Rekursion
I
Aus der Stochastik des Splittens ergibt sich
n
1 X
V quick (n) = (n−1)+ ·
V quick (k − 1) + V quick (n − k)
n
k=1
I
dies lässt sich umformen zu
n−1
2 X
V quick (n) = (n−1)+ ·
V quick (k) (n ≥ 2),
n
V quick (1) = 0
k=0
I
Abgekürzt geschrieben mit F (n) = V quick (n):
n−1
2 X
F (n) = n − 1 + ·
F (k)
n
k=0
F (0) = F (1) = 0.
Einige Werte
F (1) = 0
F (2) = 1
F (3) = 8/3 = 2.66...
F (4) = 29/6 = 4.83...
F (5) = 37/5 = 7.4
F (6) = 10.3
F (7) = 13.48...
F (8) = 16.92...
F (9) = 20.57...
F (10) = 30791/1260 = 24.43...
F (100) = 647.85...
F (1000) = 10985.9...
Die Komplexitätsaussage
I
Harmonische Zahlen
n
1 1
1 X1
1
Hn = 1 + + + . . . + =
= ln n + γ + O( )
2 3
n
j
n
j=1
Die Komplexitätsaussage
I
Harmonische Zahlen
n
1 1
1 X1
1
Hn = 1 + + + . . . + =
= ln n + γ + O( )
2 3
n
j
n
j=1
I
Theorem: Für die mittlere Anzahl der Vergleichsoperationen
von Quicksort gilt
V quick (n) = F (n) = 2 (n + 1) Hn − 4 n
und somit
V quick (n) ∼ 2 n ln n ∈ Θ(n log n)
Figure: Graph von F (n) (blau) und von 2 n ln n (rot)
Figure: Graph von F (n)/(2 n ln n)
Weitere Werte
F (104 ) = 155771.6...
F (105 ) = 0.2018... 107
F (106 ) = 0.2478... 108
F (107 ) = 0.2939... 109
F (108 ) = 0.3399... 1010
F (109 ) = 0.3860... 1011
F (1010 ) = 0.4320... 1012
Lösung der Quicksort-Rekursion
I
Rekursionsbeziehung
n−1
2X
F (n) = n − 1 +
F (i)
n
i=0
Lösung der Quicksort-Rekursion
I
Rekursionsbeziehung
n−1
2X
F (n) = n − 1 +
F (i)
n
i=0
I
Äquivalent
n F (n) = n(n − 1) + 2
n
X
i=1
F (i − 1)
(n > 0)
Lösung der Quicksort-Rekursion
I
Rekursionsbeziehung
n−1
2X
F (n) = n − 1 +
F (i)
n
i=0
I
Äquivalent
n F (n) = n(n − 1) + 2
n
X
F (i − 1)
(n > 0)
i=1
I
Durch Subtraktion
n F (n) − (n − 1) F (n − 1) = 2 (n − 1) + 2 F (n − 1)
Lösung der Quicksort-Rekursion
I
Rekursionsbeziehung
n−1
2X
F (n) = n − 1 +
F (i)
n
i=0
I
Äquivalent
n F (n) = n(n − 1) + 2
n
X
F (i − 1)
(n > 0)
i=1
I
Durch Subtraktion
n F (n) − (n − 1) F (n − 1) = 2 (n − 1) + 2 F (n − 1)
I
Umgeformt
n F (n) − (n + 1) F (n − 1) = 2 (n − 1).
Lösung der Quicksort-Rekursion (Forts.)
I
F (n) durch (n + 1) G (n) ersetzen
G (n) − G (n − 1) =
2 (n − 1)
(n > 0) , G (0) = 0
n (n + 1)
Lösung der Quicksort-Rekursion (Forts.)
I
F (n) durch (n + 1) G (n) ersetzen
G (n) − G (n − 1) =
I
2 (n − 1)
(n > 0) , G (0) = 0
n (n + 1)
Teleskop-Trick
G (n) =
n
X
i=1
n
X
{G (i) − G (i − 1)}
2 (i − 1)
i (i + 1)
i=1
n X
2
1
= 2
−
i +1
i
i=1
n
n
X
X
2
2
1
= 2
−
+2
i +1
i
i
i=1
i=1
2
= 2
− 2 + 2 Hn
n+1
=
Herunterladen